diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 8748563..d8eaa39 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -427,3 +427,6 @@
 44d3ef13208474f04a2af87ad83862a9f96802ed
 61b892921372a934c5135e6b8a4ed78e8922d809
 611b5c153ab8ad38688f78ef2360a03f55b1d62e
+
+# MSE: Rename media and modules MediaSource classes
+0be1f30b1774cbff11ea8943dd8db93a9130fd59
diff --git a/DEPS b/DEPS
index e588d6b1..6179ec3 100644
--- a/DEPS
+++ b/DEPS
@@ -171,11 +171,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': '02497d40161fc75c46fa47c28e6fef30310147b4',
+  'skia_revision': 'b5d977fae3b75ad3200c9492acdd55f710ce9450',
   # 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': 'f6d87d0ff881338e5998a4c7177490292619d55b',
+  'v8_revision': '9b2c573dec0571f9c0338ea91f7f3381414db390',
   # 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.
@@ -183,11 +183,11 @@
   # 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': '959d077f605ee90652362033240188223f5c2816',
+  'angle_revision': 'e3aee0b42a11f2c098bae8912a107e88494b37bb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '214ec337a0b2745e6c41fbb3d562fa517122812f',
+  'swiftshader_revision': 'e162b023f53956b05b26972e9ecb75985b2f2c27',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -242,7 +242,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': 'e0897515da03963f98a43f92b8809118397c416f',
+  'devtools_frontend_revision': 'b3a40936b9f019065082f9ad379de51067190089',
   # 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.
@@ -282,7 +282,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '79f8caf9154a0328a87424354bd10ab69e811185',
+  'spv_tools_revision': '8910ea5f1c7bc38f79a8b70b265cd9d1571f4b56',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -298,11 +298,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': '33466973bc4c52effb520832d538b48c38695ca5',
+  'dawn_revision': '1249ada986fc62a95439b8c8ec805fd3dff1e46d',
   # 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': '7c89615d6dd74bbb019f2d5413528baef363cec4',
+  'quiche_revision': '5f23a2d78434edd923a948c7f4f61bf2e7331e90',
   # 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.
@@ -881,7 +881,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'c22aa6b47ff6324117024f166faf82c31c86165e',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'a0ee3aa5b9115650f0e8c14f05bdf69fc87a038a',
       'condition': 'checkout_linux',
   },
 
@@ -891,7 +891,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1773f37de61efb55634bc3966510141df5ecf143',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '61bf4177c413806b3f2355b6ff6375fe4e2e8e12',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1242,7 +1242,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '3bde4517dec7e1b528202a4709785aa798abe480',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '16b67309ba836a3c24850df7608c741580f2bc29',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1518,7 +1518,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@207c622c1ef0b060d7641c9e4f56352330e1c97a',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fd7c149eef900e1fbd9af291fe3637b2a0c016c9',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index e39f8514..32fed5f 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -766,10 +766,12 @@
           },
           base::Unretained(this)),
       wc_getter, frame_tree_node_id,
-      // TODO(crbug.com/1033760): cache manager and identity_manager are used to
-      // perform real time url check, which is gated by UKM opted in. Since AW
-      // currently doesn't support UKM, this feature is not enabled.
-      /* cache_manager */ nullptr, /* identity_manager */ nullptr));
+      // TODO(crbug.com/1033760): cache manager, identity_manager and
+      // rt_lookup_service are used to perform real time URL check, which is
+      // gated by UKM opted-in. Since AW currently doesn't support UKM, this
+      // feature is not enabled.
+      /* cache_manager */ nullptr, /* identity_manager */ nullptr,
+      /* rt_lookup_service */ nullptr));
 
   if (request.resource_type ==
       static_cast<int>(blink::mojom::ResourceType::kMainFrame)) {
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 23b0820..1c8074ac 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1179,6 +1179,8 @@
     "wm/desks/desks_bar_view.h",
     "wm/desks/desks_controller.cc",
     "wm/desks/desks_histogram_enums.h",
+    "wm/desks/desks_restore_util.cc",
+    "wm/desks/desks_restore_util.h",
     "wm/desks/desks_util.cc",
     "wm/desks/new_desk_button.cc",
     "wm/desks/new_desk_button.h",
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc
index 14e4702..de3c1bd 100644
--- a/ash/app_list/views/app_list_item_view.cc
+++ b/ash/app_list/views/app_list_item_view.cc
@@ -71,7 +71,8 @@
 constexpr SkColor kFolderGridFocusRingColor = gfx::kGoogleBlue600;
 
 // The color of an item selected via right-click context menu.
-constexpr SkColor kContextSelection = SkColorSetA(gfx::kGoogleGrey100, 31);
+constexpr SkColor kContextSelection =
+    SkColorSetA(SK_ColorWHITE, 41);  // 16% opacity
 
 // The color of an item selected via right-click context menu in a folder.
 constexpr SkColor kContextSelectionFolder =
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index d1bb0089..4c68072f 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -1931,15 +1931,27 @@
   }
 
   SetAsFolderDroppingTarget(drop_target_, false);
+
+  AppListItemView* released_drag_view = nullptr;
   if (!cancel_reparent) {
     // By setting |drag_view_| to nullptr here, we prevent ClearDragState() from
     // cleaning up the newly created AppListItemView, effectively claiming
     // ownership of the newly created drag view.
     drag_view_->OnDragEnded();
+    // Hide the title if the item is being dropped into another folder, so it
+    // doesn't flash during transition. Otherwise, the item is being dropped
+    // into the root apps grid - pass the released view to
+    // AnimateToIdealBounds(), which will ensure the title remains hidden
+    // during the item view bounds animation to the target apps grid location.
+    if (folder_item_view) {
+      drag_view_->title()->SetVisible(false);
+    } else {
+      released_drag_view = drag_view_;
+    }
     drag_view_ = nullptr;
   }
   ClearDragState();
-  AnimateToIdealBounds(nullptr /* released_drag_view */);
+  AnimateToIdealBounds(released_drag_view);
   if (!folder_delegate_)
     view_structure_.SaveToMetadata();
 
@@ -2356,6 +2368,7 @@
   view_model_.Remove(model_index);
   if (!folder_delegate_)
     view_structure_.Remove(item_view);
+  item_view->title()->SetVisible(false);
   bounds_animator_->AnimateViewTo(item_view, item_view->bounds());
   bounds_animator_->SetAnimationDelegate(
       item_view, std::unique_ptr<gfx::AnimationDelegate>(
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc
index 6d1918fc..349e263 100644
--- a/ash/ash_prefs.cc
+++ b/ash/ash_prefs.cc
@@ -28,6 +28,7 @@
 #include "ash/system/session/logout_button_tray.h"
 #include "ash/touch/touch_devices_controller.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
+#include "ash/wm/desks/desks_restore_util.h"
 #include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 
@@ -44,6 +45,7 @@
   BluetoothPowerController::RegisterProfilePrefs(registry);
   CapsLockNotificationController::RegisterProfilePrefs(registry, for_test);
   contextual_tooltip::RegisterProfilePrefs(registry);
+  desks_restore_util::RegisterProfilePrefs(registry);
   DockedMagnifierControllerImpl::RegisterProfilePrefs(registry);
   LoginScreenController::RegisterProfilePrefs(registry, for_test);
   LogoutButtonTray::RegisterProfilePrefs(registry);
diff --git a/ash/assistant/assistant_screen_context_controller.cc b/ash/assistant/assistant_screen_context_controller.cc
index 36a2dca9..868adc8 100644
--- a/ash/assistant/assistant_screen_context_controller.cc
+++ b/ash/assistant/assistant_screen_context_controller.cc
@@ -180,16 +180,6 @@
   assistant_ = assistant;
 }
 
-void AssistantScreenContextController::AddModelObserver(
-    AssistantScreenContextModelObserver* observer) {
-  model_.AddObserver(observer);
-}
-
-void AssistantScreenContextController::RemoveModelObserver(
-    AssistantScreenContextModelObserver* observer) {
-  model_.RemoveObserver(observer);
-}
-
 void AssistantScreenContextController::RequestScreenshot(
     const gfx::Rect& rect,
     mojom::AssistantScreenContextController::RequestScreenshotCallback
@@ -235,23 +225,15 @@
   // Otherwise, we abort any requests in progress and reset state.
   if (new_visibility != AssistantVisibility::kVisible) {
     screen_context_request_factory_.InvalidateWeakPtrs();
-    model_.SetRequestState(ScreenContextRequestState::kIdle);
     assistant_->ClearScreenContextCache();
     return;
   }
 
   // Abort any request in progress and update request state.
   screen_context_request_factory_.InvalidateWeakPtrs();
-  model_.SetRequestState(ScreenContextRequestState::kInProgress);
 
   // Cache screen context for the entire screen.
-  assistant_->CacheScreenContext(base::BindOnce(
-      &AssistantScreenContextController::OnScreenContextRequestFinished,
-      screen_context_request_factory_.GetWeakPtr()));
-}
-
-void AssistantScreenContextController::OnScreenContextRequestFinished() {
-  model_.SetRequestState(ScreenContextRequestState::kIdle);
+  assistant_->CacheScreenContext(base::BindOnce([]() {}));
 }
 
 std::unique_ptr<ui::LayerTreeOwner>
diff --git a/ash/assistant/assistant_screen_context_controller.h b/ash/assistant/assistant_screen_context_controller.h
index 74d85f7..03c6b31 100644
--- a/ash/assistant/assistant_screen_context_controller.h
+++ b/ash/assistant/assistant_screen_context_controller.h
@@ -25,7 +25,6 @@
 namespace ash {
 
 class AssistantController;
-class AssistantScreenContextModelObserver;
 
 class ASH_EXPORT AssistantScreenContextController
     : public mojom::AssistantScreenContextController,
@@ -45,10 +44,6 @@
   // Returns a reference to the underlying model.
   const AssistantScreenContextModel* model() const { return &model_; }
 
-  // Adds/removes the specified screen context model |observer|.
-  void AddModelObserver(AssistantScreenContextModelObserver* observer);
-  void RemoveModelObserver(AssistantScreenContextModelObserver* observer);
-
   // ash::mojom::AssistantScreenContextController:
   void RequestScreenshot(
       const gfx::Rect& rect,
@@ -66,9 +61,6 @@
       base::Optional<AssistantEntryPoint> entry_point,
       base::Optional<AssistantExitPoint> exit_point) override;
 
-  // Invoked on screen context request finished event.
-  void OnScreenContextRequestFinished();
-
   std::unique_ptr<ui::LayerTreeOwner> CreateLayerForAssistantSnapshotForTest();
 
  private:
diff --git a/ash/assistant/model/BUILD.gn b/ash/assistant/model/BUILD.gn
index 9a55d57..b0238c99 100644
--- a/ash/assistant/model/BUILD.gn
+++ b/ash/assistant/model/BUILD.gn
@@ -46,6 +46,7 @@
   deps = [
     "//ash/assistant/ui:constants",
     "//ash/public/cpp",
+    "//chromeos/services/assistant/public:feature_flags",
     "//chromeos/services/assistant/public/mojom",
     "//services/content/public/cpp",
     "//ui/gfx/geometry",
diff --git a/ash/assistant/model/assistant_response.cc b/ash/assistant/model/assistant_response.cc
index 23584a71..b6e6566 100644
--- a/ash/assistant/model/assistant_response.cc
+++ b/ash/assistant/model/assistant_response.cc
@@ -10,10 +10,25 @@
 #include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/services/assistant/public/features.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
 
 namespace ash {
 
+// AssistantResponse::PendingUiElement -----------------------------------------
+
+struct AssistantResponse::PendingUiElement {
+ public:
+  PendingUiElement() = default;
+  ~PendingUiElement() = default;
+
+  PendingUiElement(const PendingUiElement&) = delete;
+  PendingUiElement& operator=(const PendingUiElement&) = delete;
+
+  std::unique_ptr<AssistantUiElement> ui_element;
+  bool is_processing = false;
+};
+
 // AssistantResponse::Processor ------------------------------------------------
 
 class AssistantResponse::Processor {
@@ -105,8 +120,44 @@
 
 void AssistantResponse::AddUiElement(
     std::unique_ptr<AssistantUiElement> ui_element) {
-  ui_elements_.push_back(std::move(ui_element));
-  NotifyUiElementAdded(ui_elements_.back().get());
+  // In processing v1, UI elements are immediately added to the response.
+  if (!chromeos::assistant::features::IsResponseProcessingV2Enabled()) {
+    ui_elements_.push_back(std::move(ui_element));
+    NotifyUiElementAdded(ui_elements_.back().get());
+    return;
+  }
+
+  // In processing v2, UI elements are first cached in a pending state...
+  auto pending_ui_element = std::make_unique<PendingUiElement>();
+  pending_ui_element->ui_element = std::move(ui_element);
+  pending_ui_element->is_processing = true;
+  pending_ui_elements_.push_back(std::move(pending_ui_element));
+
+  // ...while we perform any pre-processing necessary prior to rendering.
+  pending_ui_elements_.back()->ui_element->Process(base::BindOnce(
+      [](const base::WeakPtr<AssistantResponse>& self,
+         PendingUiElement* pending_ui_element) {
+        if (!self)
+          return;
+
+        // Indicate that |pending_ui_element| has finished processing.
+        pending_ui_element->is_processing = false;
+
+        // Add any UI elements that are ready for rendering to the response.
+        // Note that this may or may not include the |pending_ui_element| which
+        // just finished processing as we are required to add renderable UI
+        // elements to the response in the same order that they were initially
+        // pended to avoid inadvertently shuffling the response.
+        while (!self->pending_ui_elements_.empty() &&
+               !self->pending_ui_elements_.front()->is_processing) {
+          self->ui_elements_.push_back(
+              std::move(self->pending_ui_elements_.front()->ui_element));
+          self->pending_ui_elements_.pop_front();
+          self->NotifyUiElementAdded(self->ui_elements_.back().get());
+        }
+      },
+      weak_factory_.GetWeakPtr(),
+      base::Unretained(pending_ui_elements_.back().get())));
 }
 
 const std::vector<std::unique_ptr<AssistantUiElement>>&
diff --git a/ash/assistant/model/assistant_response.h b/ash/assistant/model/assistant_response.h
index cef545b..ea3a6977 100644
--- a/ash/assistant/model/assistant_response.h
+++ b/ash/assistant/model/assistant_response.h
@@ -5,6 +5,7 @@
 #ifndef ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
 #define ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
 
+#include <deque>
 #include <map>
 #include <memory>
 #include <vector>
@@ -83,11 +84,13 @@
   void NotifyUiElementAdded(const AssistantUiElement* ui_element);
   void NotifySuggestionsAdded(const std::vector<AssistantSuggestion*>&);
 
+  struct PendingUiElement;
   class Processor;
 
   friend class base::RefCounted<AssistantResponse>;
   ~AssistantResponse();
 
+  std::deque<std::unique_ptr<PendingUiElement>> pending_ui_elements_;
   std::vector<AssistantSuggestionPtr> suggestions_;
   ProcessingState processing_state_ = ProcessingState::kUnprocessed;
   bool has_tts_ = false;
@@ -102,6 +105,8 @@
 
   base::ObserverList<AssistantResponseObserver> observers_;
 
+  base::WeakPtrFactory<AssistantResponse> weak_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(AssistantResponse);
 };
 
diff --git a/ash/assistant/model/assistant_screen_context_model.cc b/ash/assistant/model/assistant_screen_context_model.cc
index ee9daa7..621522a1 100644
--- a/ash/assistant/model/assistant_screen_context_model.cc
+++ b/ash/assistant/model/assistant_screen_context_model.cc
@@ -4,36 +4,10 @@
 
 #include "ash/assistant/model/assistant_screen_context_model.h"
 
-#include "ash/assistant/model/assistant_screen_context_model_observer.h"
-
 namespace ash {
 
 AssistantScreenContextModel::AssistantScreenContextModel() = default;
 
 AssistantScreenContextModel::~AssistantScreenContextModel() = default;
 
-void AssistantScreenContextModel::AddObserver(
-    AssistantScreenContextModelObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void AssistantScreenContextModel::RemoveObserver(
-    AssistantScreenContextModelObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-void AssistantScreenContextModel::SetRequestState(
-    ScreenContextRequestState request_state) {
-  if (request_state == request_state_)
-    return;
-
-  request_state_ = request_state;
-  NotifyRequestStateChanged();
-}
-
-void AssistantScreenContextModel::NotifyRequestStateChanged() {
-  for (AssistantScreenContextModelObserver& observer : observers_)
-    observer.OnScreenContextRequestStateChanged(request_state_);
-}
-
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_screen_context_model.h b/ash/assistant/model/assistant_screen_context_model.h
index 799d832..84b065e 100644
--- a/ash/assistant/model/assistant_screen_context_model.h
+++ b/ash/assistant/model/assistant_screen_context_model.h
@@ -7,37 +7,15 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "base/observer_list.h"
 
 namespace ash {
 
-class AssistantScreenContextModelObserver;
-
-// Enumeration of screen context request states.
-enum class ScreenContextRequestState {
-  kIdle,
-  kInProgress,
-};
-
 class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantScreenContextModel {
  public:
   AssistantScreenContextModel();
   ~AssistantScreenContextModel();
 
-  // Adds/removes the specified screen context model |observer|.
-  void AddObserver(AssistantScreenContextModelObserver* observer);
-  void RemoveObserver(AssistantScreenContextModelObserver* observer);
-
-  // Sets the screen context request state.
-  void SetRequestState(ScreenContextRequestState request_state);
-
  private:
-  void NotifyRequestStateChanged();
-
-  ScreenContextRequestState request_state_ = ScreenContextRequestState::kIdle;
-
-  base::ObserverList<AssistantScreenContextModelObserver> observers_;
-
   DISALLOW_COPY_AND_ASSIGN(AssistantScreenContextModel);
 };
 
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc
index f47c3c8..6a51ac22 100644
--- a/ash/public/cpp/ash_pref_names.cc
+++ b/ash/public/cpp/ash_pref_names.cc
@@ -133,6 +133,15 @@
 // tooltips have been shown.
 const char kContextualTooltips[] = "settings.contextual_tooltip.shown_info";
 
+// A list containing the stored virtual desks names in the same order of the
+// desks in the overview desks bar. This list will be used to restore the desks,
+// their order, and their names for the primary user on first signin. If a desk
+// hasn't been renamed by the user (i.e. it uses one of the default
+// automatically-assigned desk names such as "Desk 1", "Desk 2", ... etc.), its
+// name will appear in this list as an empty string. The desk names are stored
+// as UTF8 strings.
+const char kDesksNamesList[] = "ash.desks.desks_names_list";
+
 // A boolean pref storing the enabled status of the Docked Magnifier feature.
 const char kDockedMagnifierEnabled[] = "ash.docked_magnifier.enabled";
 // A double pref storing the scale value of the Docked Magnifier feature by
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h
index 9b75cc06..3f320971 100644
--- a/ash/public/cpp/ash_pref_names.h
+++ b/ash/public/cpp/ash_pref_names.h
@@ -52,6 +52,8 @@
 
 ASH_PUBLIC_EXPORT extern const char kContextualTooltips[];
 
+ASH_PUBLIC_EXPORT extern const char kDesksNamesList[];
+
 ASH_PUBLIC_EXPORT extern const char kDockedMagnifierEnabled[];
 ASH_PUBLIC_EXPORT extern const char kDockedMagnifierScale[];
 ASH_PUBLIC_EXPORT extern const char
diff --git a/ash/public/cpp/autotest_private_api_utils.h b/ash/public/cpp/autotest_private_api_utils.h
index e5b33d7..2c18439 100644
--- a/ash/public/cpp/autotest_private_api_utils.h
+++ b/ash/public/cpp/autotest_private_api_utils.h
@@ -27,7 +27,7 @@
 // launcher, the caller is responsible for making sure the transition
 // will happen. (This is because the detecting the home launcher state
 // correctly isn't trivial).
-// Returns true if the closure is already invoked.
+// Returns true if the closure has been invoked.
 ASH_EXPORT bool WaitForLauncherState(AppListViewState state,
                                      base::OnceClosure closure);
 
diff --git a/ash/public/cpp/overview_test_api.h b/ash/public/cpp/overview_test_api.h
index cad9baa..65a48211 100644
--- a/ash/public/cpp/overview_test_api.h
+++ b/ash/public/cpp/overview_test_api.h
@@ -46,14 +46,20 @@
   OverviewTestApi();
   ~OverviewTestApi();
 
-  using DoneCallback = base::OnceCallback<void(bool)>;
+  using DoneCallback = base::OnceCallback<void(bool animation_succeeded)>;
 
-  // Set the overview mode state to |start|. Calls |done_callback| when it is
-  // done. |done_callback| will be called with a boolean if the animation
-  // is completed or canceled. If the overview mode state is already same to
-  // |start|, it does nothing but invokes |done_callback| with true.
+  // Set the overview mode state to |start|. |done_callback| will be invoked
+  // synchronously if the animation is already complete, and asynchronously if
+  // the overview state does not match |start|.
   void SetOverviewMode(bool start, DoneCallback done_callback);
 
+  // Runs the callback when overview is finished animating to |expected_state|.
+  // Passes true synchronously through |callback| if |expected_state| was
+  // already set. Otherwise |callback| is passed whether the animation succeeded
+  // asynchronously when the animation completes.
+  void WaitForOverviewState(OverviewAnimationState expected_state,
+                            DoneCallback callback);
+
   // Returns overview info for the current overview items if overview is
   // started. Otherwise, returns base::nullopt;
   base::Optional<OverviewInfo> GetOverviewInfo() const;
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc
index 5be5042..34915bf 100644
--- a/ash/shelf/hotseat_widget.cc
+++ b/ash/shelf/hotseat_widget.cc
@@ -294,6 +294,7 @@
   params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.parent = container;
+  params.layer_type = ui::LAYER_NOT_DRAWN;
   Init(std::move(params));
   set_focus_on_creation(false);
   GetFocusManager()->set_arrow_key_traversal_enabled_for_widget(true);
diff --git a/ash/shelf/shelf_config.cc b/ash/shelf/shelf_config.cc
index 7aa6e9f..68d48de9 100644
--- a/ash/shelf/shelf_config.cc
+++ b/ash/shelf/shelf_config.cc
@@ -322,10 +322,7 @@
 }
 
 SkColor ShelfConfig::GetMaximizedShelfColor() const {
-  // Using 0xFF causes clipping on the overlay candidate content, which prevent
-  // HW overlay, probably due to a bug in compositor. Fix it and use 0xFF.
-  // crbug.com/901538
-  return SkColorSetA(GetDefaultShelfColor(), 254);  // ~100% opacity
+  return SkColorSetA(GetDefaultShelfColor(), 0xFF);  // 100% opacity
 }
 
 SkColor ShelfConfig::GetThemedColorFromWallpaper(SkColor base_color) const {
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc
index c8c2645..f3de008 100644
--- a/ash/system/overview/overview_button_tray.cc
+++ b/ash/system/overview/overview_button_tray.cc
@@ -61,7 +61,7 @@
   Shell::Get()->shelf_config()->RemoveObserver(this);
 }
 
-void OverviewButtonTray::UpdateAfterLoginStatusChange(LoginStatus status) {
+void OverviewButtonTray::UpdateAfterLoginStatusChange() {
   UpdateIconVisibility();
 }
 
diff --git a/ash/system/overview/overview_button_tray.h b/ash/system/overview/overview_button_tray.h
index d37236de..4277dfd 100644
--- a/ash/system/overview/overview_button_tray.h
+++ b/ash/system/overview/overview_button_tray.h
@@ -68,7 +68,7 @@
   void OnShelfConfigUpdated() override;
 
   // TrayBackgroundView:
-  void UpdateAfterLoginStatusChange(LoginStatus status) override;
+  void UpdateAfterLoginStatusChange() override;
   void ClickedOutsideBubble() override;
   base::string16 GetAccessibleNameForTray() override;
   void HideBubbleWithView(const TrayBubbleView* bubble_view) override;
diff --git a/ash/system/session/logout_button_tray.cc b/ash/system/session/logout_button_tray.cc
index 92e592b..4308b85 100644
--- a/ash/system/session/logout_button_tray.cc
+++ b/ash/system/session/logout_button_tray.cc
@@ -117,7 +117,7 @@
   dialog_duration_ = base::TimeDelta::FromMilliseconds(duration_ms);
 }
 
-void LogoutButtonTray::UpdateAfterLoginStatusChange(LoginStatus status) {
+void LogoutButtonTray::UpdateAfterLoginStatusChange() {
   UpdateButtonTextAndImage();
 }
 
diff --git a/ash/system/session/logout_button_tray.h b/ash/system/session/logout_button_tray.h
index 4593919..b88bbf5 100644
--- a/ash/system/session/logout_button_tray.h
+++ b/ash/system/session/logout_button_tray.h
@@ -36,7 +36,7 @@
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
   // TrayBackgroundView:
-  void UpdateAfterLoginStatusChange(LoginStatus status) override;
+  void UpdateAfterLoginStatusChange() override;
   void UpdateAfterShelfChange() override;
   void UpdateBackground() override;
   void ClickedOutsideBubble() override;
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc
index 0ee0f6f..d40186e 100644
--- a/ash/system/status_area_widget.cc
+++ b/ash/system/status_area_widget.cc
@@ -112,7 +112,7 @@
   login_status_ = login_status;
 
   for (TrayBackgroundView* tray_button : tray_buttons_)
-    tray_button->UpdateAfterLoginStatusChange(login_status);
+    tray_button->UpdateAfterLoginStatusChange();
 }
 
 void StatusAreaWidget::SetSystemTrayVisibility(bool visible) {
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index fae4891..12a309b 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -345,8 +345,7 @@
   tray_container_->UpdateAfterShelfChange();
 }
 
-void TrayBackgroundView::UpdateAfterLoginStatusChange(
-    LoginStatus login_status) {
+void TrayBackgroundView::UpdateAfterLoginStatusChange() {
   // Handled in subclasses.
 }
 
diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h
index a3c3ef7..0934013 100644
--- a/ash/system/tray/tray_background_view.h
+++ b/ash/system/tray/tray_background_view.h
@@ -67,7 +67,7 @@
   virtual void UpdateAfterShelfChange();
 
   // Called to update the tray button after the login status changes.
-  virtual void UpdateAfterLoginStatusChange(LoginStatus login_status);
+  virtual void UpdateAfterLoginStatusChange();
 
   // Called whenever the bounds of the root window changes.
   virtual void UpdateAfterRootWindowBoundsChange(const gfx::Rect& old_bounds,
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc
index 9f21fcf1..1fec949b 100644
--- a/ash/system/unified/unified_system_tray.cc
+++ b/ash/system/unified/unified_system_tray.cc
@@ -298,7 +298,7 @@
   return bubble_ ? bubble_->GetBoundsInScreen() : gfx::Rect();
 }
 
-void UnifiedSystemTray::UpdateAfterLoginStatusChange(LoginStatus status) {
+void UnifiedSystemTray::UpdateAfterLoginStatusChange() {
   SetVisiblePreferred(true);
   PreferredSizeChanged();
 }
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h
index 5eccc3c..04072bb 100644
--- a/ash/system/unified/unified_system_tray.h
+++ b/ash/system/unified/unified_system_tray.h
@@ -129,7 +129,7 @@
   void HideBubbleWithView(const TrayBubbleView* bubble_view) override;
   void ClickedOutsideBubble() override;
   void UpdateAfterShelfChange() override;
-  void UpdateAfterLoginStatusChange(LoginStatus status) override;
+  void UpdateAfterLoginStatusChange() override;
   bool ShouldEnableExtraKeyboardAccessibility() override;
   const char* GetClassName() const override;
 
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc
index 8391bff6..a40fbbd 100644
--- a/ash/wm/desks/desk_mini_view.cc
+++ b/ash/wm/desks/desk_mini_view.cc
@@ -13,6 +13,7 @@
 #include "ash/wm/desks/desk_preview_view.h"
 #include "ash/wm/desks/desks_bar_view.h"
 #include "ash/wm/desks/desks_controller.h"
+#include "ash/wm/desks/desks_restore_util.h"
 #include "base/strings/string_util.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -325,12 +326,21 @@
 
   // When committing the name, do not allow an empty desk name. Revert back to
   // the default name.
+  // TODO(afakhry): Make this more robust. What if user renames a previously
+  // user-modified desk name, say from "code" to "Desk 2", and that desk
+  // happened to be in the second position. Since the new name matches the
+  // default one for this position, should we revert it (i.e. consider it
+  // `set_by_user = false`?
   if (desk_->name().empty()) {
     DesksController::Get()->RevertDeskNameToDefault(desk_);
     return;
   }
 
   OnDeskNameChanged(desk_->name());
+
+  // Only when the new desk name has been committed is when we can update the
+  // desks restore prefs.
+  desks_restore_util::UpdatePrimaryUserDesksPrefs();
 }
 
 bool DeskMiniView::IsPointOnMiniView(const gfx::Point& screen_location) const {
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index 861af7a5..a4268b3 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -14,6 +14,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desks_animations.h"
+#include "ash/wm/desks/desks_restore_util.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/desks/root_window_desk_switch_animator.h"
 #include "ash/wm/mru_window_tracker.h"
@@ -475,6 +476,9 @@
 
   base::AutoReset<bool> in_progress(&are_desks_being_modified_, true);
 
+  // The first default desk should not overwrite any desks restore data.
+  const bool is_first_ever_desk = desks_.empty();
+
   desks_.push_back(std::make_unique<Desk>(available_container_ids_.front()));
   available_container_ids_.pop();
   Desk* new_desk = desks_.back().get();
@@ -491,6 +495,9 @@
 
   for (auto& observer : observers_)
     observer.OnDeskAdded(new_desk);
+
+  if (!is_first_ever_desk)
+    desks_restore_util::UpdatePrimaryUserDesksPrefs();
 }
 
 void DesksController::RemoveDesk(const Desk* desk,
@@ -639,6 +646,14 @@
   desk->SetName(GetDeskDefaultName(GetDeskIndex(desk)), /*set_by_user=*/false);
 }
 
+void DesksController::RestoreNameOfDeskAtIndex(base::string16 name,
+                                               size_t index) {
+  DCHECK(!name.empty());
+  DCHECK_LT(index, desks_.size());
+
+  desks_[index]->SetName(std::move(name), /*set_by_user=*/true);
+}
+
 void DesksController::OnRootWindowAdded(aura::Window* root_window) {
   for (auto& desk : desks_)
     desk->OnRootWindowAdded(root_window);
@@ -706,6 +721,10 @@
                DesksSwitchSource::kUserSwitch);
 }
 
+void DesksController::OnFirstSessionStarted() {
+  desks_restore_util::RestorePrimaryUserDesks();
+}
+
 void DesksController::OnAnimationFinished(DeskAnimationBase* animation) {
   base::EraseIf(animations_, base::MatchesUniquePtr(animation));
 }
@@ -884,6 +903,8 @@
           base::NumberToString16(removed_desk_number),
           base::NumberToString16(active_desk_number)));
 
+  desks_restore_util::UpdatePrimaryUserDesksPrefs();
+
   DCHECK_LE(available_container_ids_.size(), desks_util::kMaxNumberOfDesks);
 }
 
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index 82fd9652..08a6918 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -136,6 +136,11 @@
   // it was never modified by users.
   void RevertDeskNameToDefault(Desk* desk);
 
+  // Restores the desk at |index| to the given |name|. This is only for user-
+  // modified desk names, and hence |name| should never be empty since users are
+  // not allowed to set empty names.
+  void RestoreNameOfDeskAtIndex(base::string16 name, size_t index);
+
   // Called explicitly by the RootWindowController when a root window has been
   // added or about to be removed in order to update all the available desks.
   void OnRootWindowAdded(aura::Window* root_window);
@@ -154,6 +159,7 @@
 
   // SessionObserver:
   void OnActiveUserSessionChanged(const AccountId& account_id) override;
+  void OnFirstSessionStarted() override;
 
  private:
   class DeskAnimationBase;
diff --git a/ash/wm/desks/desks_histogram_enums.h b/ash/wm/desks/desks_histogram_enums.h
index 4bdfe96b..428c7bb 100644
--- a/ash/wm/desks/desks_histogram_enums.h
+++ b/ash/wm/desks/desks_histogram_enums.h
@@ -13,7 +13,8 @@
 enum class DesksCreationRemovalSource {
   kButton = 0,
   kKeyboard = 1,
-  kMaxValue = kKeyboard,
+  kDesksRestore = 2,
+  kMaxValue = kDesksRestore,
 };
 
 // These values are logged to UMA. Entries should not be renumbered and
diff --git a/ash/wm/desks/desks_restore_util.cc b/ash/wm/desks/desks_restore_util.cc
new file mode 100644
index 0000000..8e6a23c
--- /dev/null
+++ b/ash/wm/desks/desks_restore_util.cc
@@ -0,0 +1,108 @@
+// 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 "ash/wm/desks/desks_restore_util.h"
+
+#include "ash/public/cpp/ash_pref_names.h"
+#include "ash/session/session_controller_impl.h"
+#include "ash/shell.h"
+#include "ash/wm/desks/desk.h"
+#include "ash/wm/desks/desks_controller.h"
+#include "ash/wm/desks/desks_histogram_enums.h"
+#include "ash/wm/desks/desks_util.h"
+#include "base/auto_reset.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+
+namespace ash {
+
+namespace desks_restore_util {
+
+namespace {
+
+// While restore is in progress, changes are being made to the desks and their
+// names. Those changes should not trigger an update to the prefs.
+bool g_pause_desks_prefs_updates = false;
+
+PrefService* GetPrimaryUserPrefService() {
+  return Shell::Get()->session_controller()->GetPrimaryUserPrefService();
+}
+
+}  // namespace
+
+void RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterListPref(prefs::kDesksNamesList);
+}
+
+void RestorePrimaryUserDesks() {
+  base::AutoReset<bool> in_progress(&g_pause_desks_prefs_updates, true);
+
+  PrefService* primary_user_prefs = GetPrimaryUserPrefService();
+  if (!primary_user_prefs) {
+    // Can be null in tests.
+    return;
+  }
+
+  const base::ListValue* desks_names_list =
+      primary_user_prefs->GetList(prefs::kDesksNamesList);
+
+  // First create the same number of desks.
+  const size_t restore_size = desks_names_list->GetSize();
+
+  // If we don't have any restore data, or the list is corrupt for some reason,
+  // abort.
+  if (!restore_size || restore_size >= desks_util::kMaxNumberOfDesks)
+    return;
+
+  auto* desks_controller = DesksController::Get();
+  while (desks_controller->desks().size() < restore_size)
+    desks_controller->NewDesk(DesksCreationRemovalSource::kDesksRestore);
+
+  size_t index = 0;
+  for (const auto& value : desks_names_list->GetList()) {
+    const std::string& desk_name = value.GetString();
+    // Empty desks names are just place holders for desks whose names haven't
+    // been modified by the user. Those don't need to be restored; they already
+    // have the correct default names based on their positions in the desks
+    // list.
+    if (!desk_name.empty()) {
+      desks_controller->RestoreNameOfDeskAtIndex(base::UTF8ToUTF16(desk_name),
+                                                 index);
+    }
+    ++index;
+  }
+}
+
+void UpdatePrimaryUserDesksPrefs() {
+  if (g_pause_desks_prefs_updates)
+    return;
+
+  PrefService* primary_user_prefs = GetPrimaryUserPrefService();
+  if (!primary_user_prefs) {
+    // Can be null in tests.
+    return;
+  }
+
+  ListPrefUpdate update(primary_user_prefs, prefs::kDesksNamesList);
+  base::ListValue* pref_data = update.Get();
+  pref_data->Clear();
+  const auto& desks = DesksController::Get()->desks();
+  for (const auto& desk : desks) {
+    // Desks whose names were not changed by the user, are stored as empty
+    // strings. They're just place holders to restore the correct desks count.
+    // RestorePrimaryUserDesks() restores only non-empty desks names.
+    pref_data->Append(desk->is_name_set_by_user()
+                          ? base::UTF16ToUTF8(desk->name())
+                          : std::string());
+  }
+
+  DCHECK_EQ(pref_data->GetSize(), desks.size());
+}
+
+}  // namespace desks_restore_util
+
+}  // namespace ash
diff --git a/ash/wm/desks/desks_restore_util.h b/ash/wm/desks/desks_restore_util.h
new file mode 100644
index 0000000..03fa92d0
--- /dev/null
+++ b/ash/wm/desks/desks_restore_util.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WM_DESKS_DESKS_RESTORE_UTIL_H_
+#define ASH_WM_DESKS_DESKS_RESTORE_UTIL_H_
+
+class PrefRegistrySimple;
+
+namespace ash {
+
+namespace desks_restore_util {
+
+// Registers the profile prefs needed for restoring virtual desks.
+void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+// Called when `OnFirstSessionStarted()` is triggered to restore the desks, and
+// their names from the primary user's prefs.
+void RestorePrimaryUserDesks();
+
+// Called to update the desks restore prefs for the primary user, whenever a
+// change to the desks count or their names is triggered.
+void UpdatePrimaryUserDesksPrefs();
+
+}  // namespace desks_restore_util
+
+}  // namespace ash
+
+#endif  // ASH_WM_DESKS_DESKS_RESTORE_UTIL_H_
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index e054322..fb32c41 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -8,11 +8,14 @@
 #include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/multi_user/multi_user_window_manager_impl.h"
 #include "ash/public/cpp/ash_features.h"
+#include "ash/public/cpp/ash_pref_names.h"
+#include "ash/public/cpp/ash_prefs.h"
 #include "ash/public/cpp/event_rewriter_controller.h"
 #include "ash/public/cpp/multi_user_window_manager.h"
 #include "ash/public/cpp/multi_user_window_manager_delegate.h"
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/screen_util.h"
+#include "ash/session/session_controller_impl.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shell.h"
@@ -50,6 +53,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/prefs/testing_pref_service.h"
 #include "components/session_manager/session_manager_types.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/window_parenting_client.h"
@@ -1463,6 +1469,27 @@
             new_desk_button->GetBackgroundColorForTesting());
 }
 
+namespace {
+
+PrefService* GetPrimaryUserPrefService() {
+  return Shell::Get()->session_controller()->GetPrimaryUserPrefService();
+}
+
+// Verifies that the desks restore prefs in the given |user_prefs| matches the
+// given list of |desks_names|.
+void VerifyDesksRestoreData(PrefService* user_prefs,
+                            const std::vector<std::string>& desks_names) {
+  const base::ListValue* desks_restore_names =
+      user_prefs->GetList(prefs::kDesksNamesList);
+  ASSERT_EQ(desks_names.size(), desks_restore_names->GetSize());
+
+  size_t index = 0;
+  for (const auto& value : desks_restore_names->GetList())
+    EXPECT_EQ(desks_names[index++], value.GetString());
+}
+
+}  // namespace
+
 class DesksEditableNamesTest : public AshTestBase {
  public:
   DesksEditableNamesTest() = default;
@@ -1489,7 +1516,10 @@
     ASSERT_TRUE(desks_bar_view_);
   }
 
-  void ClickOnDeskNameViewAtIndex(int index) {
+  void ClickOnDeskNameViewAtIndex(size_t index) {
+    ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
+    ASSERT_LT(index, desks_bar_view_->mini_views().size());
+
     auto* desk_name_view =
         desks_bar_view_->mini_views()[index]->desk_name_view();
     auto* generator = GetEventGenerator();
@@ -1527,6 +1557,10 @@
   EXPECT_FALSE(desk_name_view_2->HasFocus());
   auto* desk_2 = controller()->desks()[1].get();
   EXPECT_FALSE(desk_2->is_name_set_by_user());
+
+  // Desks restore data should reflect two default-named desks.
+  VerifyDesksRestoreData(GetPrimaryUserPrefService(),
+                         {std::string(), std::string()});
 }
 
 TEST_F(DesksEditableNamesTest, NamesSetByUsersAreNotOverwritten) {
@@ -1560,6 +1594,11 @@
   EXPECT_TRUE(desk_1->is_name_set_by_user());
   EXPECT_FALSE(desk_2->is_name_set_by_user());
 
+  // Renaming desks via the mini views trigger an update to the desks restore
+  // prefs.
+  VerifyDesksRestoreData(GetPrimaryUserPrefService(),
+                         {std::string("code"), std::string()});
+
   // Add a third desk and remove the second. Both operations should not affect
   // the user-modified desk names.
   NewDesk();
@@ -1568,11 +1607,18 @@
   EXPECT_TRUE(desk_1->is_name_set_by_user());
   EXPECT_FALSE(desk_2->is_name_set_by_user());
   EXPECT_FALSE(desk_3->is_name_set_by_user());
+
+  // Adding a desk triggers an update to the restore prefs.
+  VerifyDesksRestoreData(GetPrimaryUserPrefService(),
+                         {std::string("code"), std::string(), std::string()});
+
   RemoveDesk(desk_2);
   EXPECT_TRUE(desk_1->is_name_set_by_user());
   EXPECT_FALSE(desk_3->is_name_set_by_user());
   // Desk 3 will now be renamed to "Desk 2".
   EXPECT_EQ(base::UTF8ToUTF16("Desk 2"), desk_3->name());
+  VerifyDesksRestoreData(GetPrimaryUserPrefService(),
+                         {std::string("code"), std::string()});
 
   overview_controller->EndOverview();
   overview_controller->StartOverview();
@@ -1601,6 +1647,8 @@
   EXPECT_FALSE(desk_1->name().empty());
   EXPECT_FALSE(desk_1->is_name_set_by_user());
   EXPECT_EQ(base::UTF8ToUTF16("Desk 1"), desk_1->name());
+  VerifyDesksRestoreData(GetPrimaryUserPrefService(),
+                         {std::string(), std::string()});
 }
 
 class TabletModeDesksTest : public DesksTest {
@@ -2359,6 +2407,8 @@
   MultiUserWindowManager* multi_user_window_manager() {
     return multi_user_window_manager_.get();
   }
+  TestingPrefServiceSimple* user_1_prefs() { return user_1_prefs_; }
+  TestingPrefServiceSimple* user_2_prefs() { return user_2_prefs_; }
 
   // AshTestBase:
   void SetUp() override {
@@ -2366,16 +2416,27 @@
     TestSessionControllerClient* session_controller =
         GetSessionControllerClient();
     session_controller->Reset();
-    session_controller->AddUserSession(kUser1Email);
-    session_controller->AddUserSession(kUser2Email);
 
-    // Simulate user 1 login.
-    SwitchActiveUser(GetUser1AccountId());
-    multi_user_window_manager_ =
-        MultiUserWindowManager::Create(this, GetUser1AccountId());
-    MultiUserWindowManagerImpl::Get()->SetAnimationSpeedForTest(
-        MultiUserWindowManagerImpl::ANIMATION_SPEED_DISABLED);
-    session_controller->SetSessionState(session_manager::SessionState::ACTIVE);
+    // Inject our own PrefServices for each user which enables us to setup the
+    // desks restore data before the user signs in.
+    auto user_1_prefs = std::make_unique<TestingPrefServiceSimple>();
+    user_1_prefs_ = user_1_prefs.get();
+    RegisterUserProfilePrefs(user_1_prefs_->registry(), /*for_test=*/true);
+    auto user_2_prefs = std::make_unique<TestingPrefServiceSimple>();
+    user_2_prefs_ = user_2_prefs.get();
+    RegisterUserProfilePrefs(user_2_prefs_->registry(), /*for_test=*/true);
+    session_controller->AddUserSession(kUser1Email,
+                                       user_manager::USER_TYPE_REGULAR,
+                                       /*enable_settings=*/true,
+                                       /*provide_pref_service=*/false);
+    session_controller->SetUserPrefService(GetUser1AccountId(),
+                                           std::move(user_1_prefs));
+    session_controller->AddUserSession(kUser2Email,
+                                       user_manager::USER_TYPE_REGULAR,
+                                       /*enable_settings=*/true,
+                                       /*provide_pref_service=*/false);
+    session_controller->SetUserPrefService(GetUser2AccountId(),
+                                           std::move(user_2_prefs));
   }
 
   void TearDown() override {
@@ -2402,13 +2463,39 @@
     GetSessionControllerClient()->SwitchActiveUser(account_id);
   }
 
+  // Initializes the given |prefs| with a desks restore data of 3 desks, with
+  // the third desk named "code", and the rest are default-named.
+  void InitPrefsWithDesksRestoreData(PrefService* prefs) {
+    DCHECK(prefs);
+    ListPrefUpdate update(prefs, prefs::kDesksNamesList);
+    base::ListValue* pref_data = update.Get();
+    ASSERT_TRUE(pref_data->empty());
+    pref_data->Append(std::string());
+    pref_data->Append(std::string());
+    pref_data->Append(std::string("code"));
+  }
+
+  void SimulateUserLogin(const AccountId& account_id) {
+    SwitchActiveUser(account_id);
+    multi_user_window_manager_ =
+        MultiUserWindowManager::Create(this, account_id);
+    MultiUserWindowManagerImpl::Get()->SetAnimationSpeedForTest(
+        MultiUserWindowManagerImpl::ANIMATION_SPEED_DISABLED);
+    GetSessionControllerClient()->SetSessionState(
+        session_manager::SessionState::ACTIVE);
+  }
+
  private:
   std::unique_ptr<MultiUserWindowManager> multi_user_window_manager_;
 
+  TestingPrefServiceSimple* user_1_prefs_ = nullptr;
+  TestingPrefServiceSimple* user_2_prefs_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(DesksMultiUserTest);
 };
 
 TEST_F(DesksMultiUserTest, SwitchUsersBackAndForth) {
+  SimulateUserLogin(GetUser1AccountId());
   auto* controller = DesksController::Get();
   NewDesk();
   NewDesk();
@@ -2465,6 +2552,7 @@
 }
 
 TEST_F(DesksMultiUserTest, RemoveDesks) {
+  SimulateUserLogin(GetUser1AccountId());
   // Create two desks with several windows with different app types that
   // belong to different users.
   auto* controller = DesksController::Get();
@@ -2561,6 +2649,7 @@
 }
 
 TEST_F(DesksMultiUserTest, SwitchingUsersEndsOverview) {
+  SimulateUserLogin(GetUser1AccountId());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->StartOverview());
   EXPECT_TRUE(overview_controller->InOverviewSession());
@@ -2568,6 +2657,61 @@
   EXPECT_FALSE(overview_controller->InOverviewSession());
 }
 
+using DesksRestoreMultiUserTest = DesksMultiUserTest;
+
+TEST_F(DesksRestoreMultiUserTest, DesksRestoredFromPrimaryUserPrefsOnly) {
+  InitPrefsWithDesksRestoreData(user_1_prefs());
+  SimulateUserLogin(GetUser1AccountId());
+  // User 1 is the first to login, hence the primary user.
+  auto* controller = DesksController::Get();
+  const auto& desks = controller->desks();
+
+  auto verify_desks = [&](const std::string& trace_name) {
+    SCOPED_TRACE(trace_name);
+    EXPECT_EQ(3u, desks.size());
+    EXPECT_EQ(base::UTF8ToUTF16("Desk 1"), desks[0]->name());
+    EXPECT_EQ(base::UTF8ToUTF16("Desk 2"), desks[1]->name());
+    EXPECT_EQ(base::UTF8ToUTF16("code"), desks[2]->name());
+    // Restored non-default names should be marked as `set_by_user`.
+    EXPECT_FALSE(desks[0]->is_name_set_by_user());
+    EXPECT_FALSE(desks[1]->is_name_set_by_user());
+    EXPECT_TRUE(desks[2]->is_name_set_by_user());
+  };
+
+  verify_desks("Before switching users");
+
+  // Switching users should not change anything as restoring happens only at
+  // the time when the first user signs in.
+  SwitchActiveUser(GetUser2AccountId());
+  verify_desks("After switching users");
+}
+
+TEST_F(DesksRestoreMultiUserTest,
+       ChangesMadeBySecondaryUserAffectsOnlyPrimaryUserPrefs) {
+  InitPrefsWithDesksRestoreData(user_1_prefs());
+  SimulateUserLogin(GetUser1AccountId());
+  // Switch to user 2 (secondary) and make some desks changes. Those changes
+  // should be persisted to user 1's prefs only.
+  SwitchActiveUser(GetUser2AccountId());
+
+  auto* controller = DesksController::Get();
+  const auto& desks = controller->desks();
+  ASSERT_EQ(3u, desks.size());
+
+  // Create a fourth desk.
+  NewDesk();
+  VerifyDesksRestoreData(user_1_prefs(), {std::string(), std::string(),
+                                          std::string("code"), std::string()});
+  // User 2's prefs are unaffected (empty list of desks).
+  VerifyDesksRestoreData(user_2_prefs(), {});
+
+  // Delete the second desk.
+  RemoveDesk(desks[1].get());
+  VerifyDesksRestoreData(user_1_prefs(),
+                         {std::string(), std::string("code"), std::string()});
+  VerifyDesksRestoreData(user_2_prefs(), {});
+}
+
 }  // namespace
 
 // Simulates the same behavior of event rewriting that key presses go through.
diff --git a/ash/wm/overview/overview_test_api.cc b/ash/wm/overview/overview_test_api.cc
index a956ae0..c485284 100644
--- a/ash/wm/overview/overview_test_api.cc
+++ b/ash/wm/overview/overview_test_api.cc
@@ -47,6 +47,27 @@
     waiter->Cancel();
 }
 
+void OverviewTestApi::WaitForOverviewState(
+    OverviewAnimationState expected_state,
+    DoneCallback callback) {
+  auto* overview_controller = Shell::Get()->overview_controller();
+  const bool overview_finished_showing =
+      overview_controller->InOverviewSession() &&
+      !overview_controller->IsInStartAnimation();
+  const bool overview_finished_hiding =
+      !overview_controller->InOverviewSession() &&
+      !overview_controller->IsCompletingShutdownAnimations();
+  if ((expected_state == OverviewAnimationState::kEnterAnimationComplete &&
+       overview_finished_showing) ||
+      (expected_state == OverviewAnimationState::kExitAnimationComplete &&
+       overview_finished_hiding)) {
+    std::move(callback).Run(/*animation_succeeded=*/true);
+    return;
+  }
+
+  new OverviewAnimationStateWaiter(expected_state, std::move(callback));
+}
+
 base::Optional<OverviewInfo> OverviewTestApi::GetOverviewInfo() const {
   auto* overview_controller = Shell::Get()->overview_controller();
   if (!overview_controller->InOverviewSession())
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 85bc736..09c4740 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -2317,10 +2317,7 @@
       cflags += [ "-g2" ]
     }
 
-    # TODO: Remove cros specific logic once cros clang supports
-    # "-debug-info-kind=constructor" option.
-    if (is_clang && !is_nacl &&
-        default_toolchain != "//build/toolchain/cros:target") {
+    if (is_clang && !is_nacl) {
       cflags += [
         "-Xclang",
         "-debug-info-kind=constructor",
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 69a614d5..d0241b0d 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200224.1.1
\ No newline at end of file
+0.20200224.2.1
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index baf39ad3..69a614d5 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200224.0.1
\ No newline at end of file
+0.20200224.1.1
\ No newline at end of file
diff --git a/build/fuchsia/remote_cmd.py b/build/fuchsia/remote_cmd.py
index a1f974e..93ce32ce 100644
--- a/build/fuchsia/remote_cmd.py
+++ b/build/fuchsia/remote_cmd.py
@@ -130,4 +130,9 @@
     scp_command += [dest]
 
     _SSH_LOGGER.debug(' '.join(scp_command))
-    subprocess.check_call(scp_command, stdout=open(os.devnull, 'w'))
+    try:
+      scp_output = subprocess.check_output(scp_command,
+                                           stderr=subprocess.STDOUT)
+    except subprocess.CalledProcessError as error:
+      _SSH_LOGGER.info(error.output)
+      raise
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 2d09bdb..fb9f477 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -514,6 +514,7 @@
   "javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java",
   "javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java",
   "javatests/src/org/chromium/chrome/browser/translate/TranslateOptionsTest.java",
+  "javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java",
   "javatests/src/org/chromium/chrome/browser/undo_tab_close_snackbar/UndoBarControllerTest.java",
   "javatests/src/org/chromium/chrome/browser/usage_stats/TabSuspensionTest.java",
   "javatests/src/org/chromium/chrome/browser/video/FullscreenVideoTest.java",
diff --git a/chrome/android/feed/merging.md b/chrome/android/feed/merging.md
index 9ed8434..ec7052f9 100644
--- a/chrome/android/feed/merging.md
+++ b/chrome/android/feed/merging.md
@@ -4,4 +4,4 @@
 and [feed wire protos](https://cs.chromium.org/chromium/src/components/feed/core/proto/wire/)
 are hand-merged from https://chromium.googlesource.com/feed regularly.
 
-Last merged commit ID: 39fe4a79d4144e2e1eb170a7ba0a49b7510162f8
+Last merged commit ID: aa5e906377aaec1263ec77fe66c0e069217af54d
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 927064f..1dbf431 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -800,9 +800,8 @@
     public void startNativeInitialization() {
         try (TraceEvent e = TraceEvent.scoped("ChromeTabbedActivity.startNativeInitialization")) {
             // This is on the critical path so don't delay.
-            if (CachedFeatureFlags.isNightModeAvailable()
-                    && ChromeFeatureList.isEnabled(
-                            ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING)) {
+            if (ChromeFeatureList.isEnabled(
+                        ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING)) {
                 WebContentsDarkModeController.createInstance();
             }
             setupCompositorContent();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java
index 5c36a63..11e1eaf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java
@@ -119,7 +119,7 @@
 
     private static void recordHistogram(@AnnouncementNotificationEvent int event) {
         RecordHistogram.recordEnumeratedHistogram("Notifications.Announcement.Events", event,
-                org.chromium.chrome.browser.announcement.AnnouncementNotificationEvent.MAX_VALUE);
+                AnnouncementNotificationEvent.MAX_VALUE + 1);
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
index 9753ef6..2c40dd0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -7,7 +7,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.base.BuildInfo;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.FieldTrialList;
 import org.chromium.base.SysUtils;
@@ -200,7 +199,6 @@
      * Do not add new simple boolean flags here, use {@link #cacheNativeFlags} instead.
      */
     public static void cacheAdditionalNativeFlags() {
-        cacheNightModeAvailable();
         cacheNetworkServiceWarmUpEnabled();
         cacheNativeTabSwitcherUiFlags();
         cacheReachedCodeProfilerTrialGroup();
@@ -277,36 +275,6 @@
     }
 
     /**
-     * Cache whether or not night mode is available (i.e. night mode experiment is enabled) so on
-     * next startup, the value can be made available immediately.
-     */
-    public static void cacheNightModeAvailable() {
-        boolean available = ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_NIGHT_MODE)
-                || (BuildInfo.isAtLeastQ()
-                        && ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_NIGHT_MODE_FOR_Q));
-        SharedPreferencesManager.getInstance().writeBoolean(
-                ChromePreferenceKeys.FLAGS_CACHED_NIGHT_MODE_AVAILABLE, available);
-    }
-
-    /**
-     * @return Whether or not night mode experiment is enabled (i.e. night mode experiment is
-     *         enabled).
-     */
-    public static boolean isNightModeAvailable() {
-        return getConsistentBooleanValue(
-                ChromePreferenceKeys.FLAGS_CACHED_NIGHT_MODE_AVAILABLE, true);
-    }
-
-    /**
-     * Toggles whether the night mode experiment is enabled for testing. Should be reset back to
-     * null after the test has finished.
-     */
-    @VisibleForTesting
-    public static void setNightModeAvailableForTesting(@Nullable Boolean available) {
-        sBoolValuesReturned.put(ChromePreferenceKeys.FLAGS_CACHED_NIGHT_MODE_AVAILABLE, available);
-    }
-
-    /**
      * @return Whether or not night mode experiment is enabled (i.e. night mode experiment is
      *         enabled) for custom tabs.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java
index c36552a..0ad1f7f9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java
@@ -12,7 +12,6 @@
 import org.chromium.base.CommandLine;
 import org.chromium.chrome.browser.ChromeBaseAppCompatActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 
 /**
@@ -59,8 +58,7 @@
     public static NightModeStateProvider getInstance() {
         if (sInstance == null) {
             if (CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_ENABLE_NIGHT_MODE)
-                    || !NightModeUtils.isNightModeSupported()
-                    || !CachedFeatureFlags.isNightModeAvailable()) {
+                    || !NightModeUtils.isNightModeSupported()) {
                 sInstance = new DummyNightModeStateProvider();
             } else {
                 sInstance = new GlobalNightModeStateController(SystemNightModeMonitor.getInstance(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index a5e15d3a..50110ad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -1102,15 +1102,18 @@
 
         // This will be called between inflation and initialization. For those calls, using a null
         // ColorStateList should have no visible impact to the user.
-        ColorStateList colorStateList = mAssistantVoiceSearchService == null
+        ColorStateList micColorStateList = mAssistantVoiceSearchService == null
                 ? null
                 : mAssistantVoiceSearchService.getMicButtonColorStateList(
                         primaryColor, getContext());
-        ApiCompatibilityUtils.setImageTintList(mMicButton, colorStateList);
-        ApiCompatibilityUtils.setImageTintList(mDeleteButton, colorStateList);
+        ApiCompatibilityUtils.setImageTintList(mMicButton, micColorStateList);
 
         final boolean useDarkColors =
                 !ColorUtils.shouldUseLightForegroundOnBackground(primaryColor);
+        ColorStateList colorStateList =
+                ChromeColors.getPrimaryIconTint(getContext(), !useDarkColors);
+        ApiCompatibilityUtils.setImageTintList(mDeleteButton, colorStateList);
+
         // If the URL changed colors and is not focused, update the URL to account for the new
         // color scheme.
         if (mUrlCoordinator.setUseDarkTextColors(useDarkColors) && !mUrlBar.hasFocus()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
index db371cb9..4db0fcdd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -18,7 +18,6 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.datareduction.settings.DataReductionPreferenceFragment;
-import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.night_mode.NightModeUtils;
@@ -196,7 +195,7 @@
         Preference homepagePref = addPreferenceIfAbsent(PREF_HOMEPAGE);
         setOnOffSummary(homepagePref, HomepageManager.isHomepageEnabled());
 
-        if (NightModeUtils.isNightModeSupported() && CachedFeatureFlags.isNightModeAvailable()) {
+        if (NightModeUtils.isNightModeSupported()) {
             addPreferenceIfAbsent(PREF_UI_THEME);
         } else {
             removePreferenceIfPresent(PREF_UI_THEME);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java
index 0c0fa93..542387f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java
@@ -13,6 +13,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -73,38 +74,23 @@
     ArrayList<PropertyModel> createTopRowPropertyModels(
             ShareSheetBottomSheetContent bottomSheet, Activity activity) {
         ArrayList<PropertyModel> models = new ArrayList<>();
-        // QR Codes
-        PropertyModel qrcodePropertyModel = mPropertyModelBuilder.createPropertyModel(
-                AppCompatResources.getDrawable(activity, R.drawable.qr_code),
-                activity.getResources().getString(R.string.qr_code_share_icon_label),
-                (currentActivity)
-                        -> {
-                    mBottomSheetController.hideContent(bottomSheet, true);
-                    QrCodeCoordinator qrCodeCoordinator = new QrCodeCoordinator(activity);
-                    qrCodeCoordinator.show();
-                },
-                /*isFirstParty=*/true);
-        models.add(qrcodePropertyModel);
-
-        // Send Tab To Self
-        PropertyModel sttsPropertyModel =
-                mPropertyModelBuilder
-                        .createPropertyModel(
-                                AppCompatResources.getDrawable(activity, R.drawable.send_tab),
-                                activity.getResources().getString(
-                                        R.string.send_tab_to_self_share_activity_title),
-                                (shareParams)
-                                        -> {
-                                    mBottomSheetController.hideContent(bottomSheet, true);
-                                    SendTabToSelfShareActivity.actionHandler(activity,
-                                            mActivityTabProvider.get()
-                                                    .getWebContents()
-                                                    .getNavigationController()
-                                                    .getVisibleEntry(),
-                                            mBottomSheetController);
-                                },
-                                /*isFirstParty=*/true);
-        models.add(sttsPropertyModel);
+        // ScreenShot
+        PropertyModel screenshotPropertyModel = null;
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARE_SCREENSHOT)) {
+            screenshotPropertyModel = mPropertyModelBuilder.createPropertyModel(
+                    AppCompatResources.getDrawable(activity, R.drawable.screenshot),
+                    activity.getResources().getString(R.string.sharing_screenshot),
+                    (shareParams)
+                            -> {
+                        mBottomSheetController.hideContent(bottomSheet, true);
+                        Tab tab = mActivityTabProvider.get();
+                        ScreenshotCoordinator screenshotCoordinator =
+                                new ScreenshotCoordinator(activity, tab);
+                        screenshotCoordinator.handleScreenshot();
+                    },
+                    /*isFirstParty=*/true);
+            models.add(screenshotPropertyModel);
+        }
 
         // Copy URL
         PropertyModel copyPropertyModel = mPropertyModelBuilder.createPropertyModel(
@@ -124,23 +110,40 @@
                 }, /*isFirstParty=*/true);
         models.add(copyPropertyModel);
 
-         // ScreenShot
-        PropertyModel screenshotPropertyModel = null;
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARE_SCREENSHOT)) {
-            screenshotPropertyModel = mPropertyModelBuilder.createPropertyModel(
-                    AppCompatResources.getDrawable(activity, R.drawable.screenshot),
-                    activity.getResources().getString(R.string.sharing_screenshot),
-                    (shareParams)
-                            -> {
-                        mBottomSheetController.hideContent(bottomSheet, true);
-                        Tab tab = mActivityTabProvider.get();
-                        ScreenshotCoordinator screenshotCoordinator =
-                                new ScreenshotCoordinator(activity, tab);
-                        screenshotCoordinator.handleScreenshot();
-                    },
-                    /*isFirstParty=*/true);
-            models.add(screenshotPropertyModel);
-        }
+        // Send Tab To Self
+        PropertyModel sttsPropertyModel =
+                mPropertyModelBuilder
+                        .createPropertyModel(
+                                AppCompatResources.getDrawable(activity, R.drawable.send_tab),
+                                activity.getResources().getString(
+                                        R.string.send_tab_to_self_share_activity_title),
+                                (shareParams)
+                                        -> {
+                                    RecordUserAction.record(
+                                            "SharingHubAndroid.SendTabToSelfSelected");
+                                    mBottomSheetController.hideContent(bottomSheet, true);
+                                    SendTabToSelfShareActivity.actionHandler(activity,
+                                            mActivityTabProvider.get()
+                                                    .getWebContents()
+                                                    .getNavigationController()
+                                                    .getVisibleEntry(),
+                                            mBottomSheetController);
+                                },
+                                /*isFirstParty=*/true);
+        models.add(sttsPropertyModel);
+
+        // QR Codes
+        PropertyModel qrcodePropertyModel = mPropertyModelBuilder.createPropertyModel(
+                AppCompatResources.getDrawable(activity, R.drawable.qr_code),
+                activity.getResources().getString(R.string.qr_code_share_icon_label),
+                (currentActivity)
+                        -> {
+                    mBottomSheetController.hideContent(bottomSheet, true);
+                    QrCodeCoordinator qrCodeCoordinator = new QrCodeCoordinator(activity);
+                    qrCodeCoordinator.show();
+                },
+                /*isFirstParty=*/true);
+        models.add(qrcodePropertyModel);
 
         return models;
     }
@@ -156,6 +159,7 @@
                 activity.getResources().getString(R.string.sharing_more_icon_label),
                 (shareParams)
                         -> {
+                    RecordUserAction.record("SharingHubAndroid.MoreSelected");
                     mBottomSheetController.hideContent(bottomSheet, true);
                     ShareHelper.showDefaultShareUi(params);
                 },
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java
index 100b5dc..0dc9ec88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java
@@ -13,6 +13,7 @@
 import android.graphics.drawable.Drawable;
 import android.view.View.OnClickListener;
 
+import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -54,6 +55,7 @@
             PropertyModel propertyModel =
                     createPropertyModel(ShareHelper.loadIconForResolveInfo(info, mPackageManager),
                             (String) info.loadLabel(mPackageManager), (shareParams) -> {
+                                RecordUserAction.record("SharingHubAndroid.ThirdPartyAppSelected");
                                 ActivityInfo ai = info.activityInfo;
 
                                 ComponentName component =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
index a338fd6..184c0f54 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
@@ -143,6 +143,7 @@
         mTabProvider.addObserver(new Callback<Tab>() {
             @Override
             public void onResult(Tab tab) {
+                if (tab == null) return;
                 TabImpl tabImpl = (TabImpl) tab;
                 final Tracker tracker = TrackerFactory.getTrackerForProfile(tabImpl.getProfile());
                 final Runnable completeRunnable = () -> {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
index 91ef087..5932fc1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
@@ -111,11 +111,12 @@
                 mNativeArCoreJavaUtils, ArCoreJavaUtils.this, surface, rotation, width, height);
     }
 
-    public void onDrawingSurfaceTouch(boolean isTouching, float x, float y) {
+    public void onDrawingSurfaceTouch(
+            boolean isPrimary, boolean isTouching, int pointerId, float x, float y) {
         if (DEBUG_LOGS) Log.i(TAG, "onDrawingSurfaceTouch");
         if (mNativeArCoreJavaUtils == 0) return;
-        ArCoreJavaUtilsJni.get().onDrawingSurfaceTouch(
-                mNativeArCoreJavaUtils, ArCoreJavaUtils.this, isTouching, x, y);
+        ArCoreJavaUtilsJni.get().onDrawingSurfaceTouch(mNativeArCoreJavaUtils, ArCoreJavaUtils.this,
+                isPrimary, isTouching, pointerId, x, y);
     }
 
     public void onDrawingSurfaceDestroyed() {
@@ -139,7 +140,7 @@
         void onDrawingSurfaceReady(long nativeArCoreJavaUtils, ArCoreJavaUtils caller,
                 Surface surface, int rotation, int width, int height);
         void onDrawingSurfaceTouch(long nativeArCoreJavaUtils, ArCoreJavaUtils caller,
-                boolean touching, float x, float y);
+                boolean primary, boolean touching, int pointerId, float x, float y);
         void onDrawingSurfaceDestroyed(long nativeArCoreJavaUtils, ArCoreJavaUtils caller);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArImmersiveOverlay.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArImmersiveOverlay.java
index 4a1b9c3..22e612d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArImmersiveOverlay.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArImmersiveOverlay.java
@@ -31,13 +31,16 @@
 import org.chromium.ui.display.DisplayAndroidManager;
 import org.chromium.ui.widget.Toast;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Provides a fullscreen overlay for immersive AR mode.
  */
 public class ArImmersiveOverlay
         implements SurfaceHolder.Callback2, View.OnTouchListener, ScreenOrientationDelegate {
     private static final String TAG = "ArImmersiveOverlay";
-    private static final boolean DEBUG_LOGS = false;
+    private static final boolean DEBUG_LOGS = true;
 
     private ArCoreJavaUtils mArCoreJavaUtils;
     private ChromeActivity mActivity;
@@ -46,12 +49,20 @@
     private boolean mCleanupInProgress;
     private SurfaceUiWrapper mSurfaceUi;
 
+    // Set containing all currently touching pointers.
+    private HashMap<Integer, PointerData> mPointerIdToData;
+    // ID of primary pointer (if present).
+    private Integer mPrimaryPointerId;
+
     public void show(
             @NonNull ChromeActivity activity, @NonNull ArCoreJavaUtils caller, boolean useOverlay) {
         if (DEBUG_LOGS) Log.i(TAG, "constructor");
         mArCoreJavaUtils = caller;
         mActivity = activity;
 
+        mPointerIdToData = new HashMap<Integer, PointerData>();
+        mPrimaryPointerId = null;
+
         // Choose a concrete implementation to create a drawable Surface and make it fullscreen.
         // It forwards SurfaceHolder callbacks and touch events to this ArImmersiveOverlay object.
         if (useOverlay) {
@@ -121,6 +132,18 @@
         }
     }
 
+    private class PointerData {
+        public float x;
+        public float y;
+        public boolean touching;
+
+        public PointerData(float x, float y, boolean touching) {
+            this.x = x;
+            this.y = y;
+            this.touching = touching;
+        }
+    }
+
     private class SurfaceUiCompositor implements SurfaceUiWrapper {
         private SurfaceView mSurfaceView;
         private CompositorView mCompositorView;
@@ -185,13 +208,118 @@
     public boolean onTouch(View v, MotionEvent ev) {
         // Only forward primary actions, ignore more complex events such as secondary pointer
         // touches. Ignore batching since we're only sending one ray pose per frame.
-        if (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE
-                || ev.getAction() == MotionEvent.ACTION_UP
-                || ev.getAction() == MotionEvent.ACTION_CANCEL) {
-            boolean touching = ev.getAction() != MotionEvent.ACTION_UP
-                    && ev.getAction() != MotionEvent.ACTION_CANCEL;
-            if (DEBUG_LOGS) Log.i(TAG, "onTouch touching=" + touching);
-            mArCoreJavaUtils.onDrawingSurfaceTouch(touching, ev.getX(0), ev.getY(0));
+
+        if (DEBUG_LOGS) {
+            Log.i(TAG,
+                    "Received motion event, action: " + MotionEvent.actionToString(ev.getAction())
+                            + ", pointer count: " + ev.getPointerCount()
+                            + ", action index: " + ev.getActionIndex());
+            for (int i = 0; i < ev.getPointerCount(); i++) {
+                Log.i(TAG,
+                        "Pointer index: " + i + ", id: " + ev.getPointerId(i) + ", coordinates: ("
+                                + ev.getX(i) + ", " + ev.getY(i) + ")");
+            }
+        }
+
+        final int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP
+                || action == MotionEvent.ACTION_POINTER_DOWN
+                || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_CANCEL
+                || action == MotionEvent.ACTION_MOVE) {
+            // ACTION_DOWN - gesture starts. Pointer with index 0 will be considered as a primary
+            // pointer until it's raised. Then, there will be no primary pointer until the
+            // gesture ends (ACTION_UP / ACTION_CANCEL).
+            if (action == MotionEvent.ACTION_DOWN) {
+                int pointerId = ev.getPointerId(0);
+
+                // Remember primary pointer's ID. The start of the gesture is the only time when the
+                // primary pointer is set.
+                mPrimaryPointerId = pointerId;
+                mPointerIdToData.put(
+                        mPrimaryPointerId, new PointerData(ev.getX(0), ev.getY(0), true));
+
+                // Send the events to the device.
+                // This needs to happen after we have updated the state.
+                sendMotionEvents(false);
+            }
+
+            // ACTION_UP - gesture ends.
+            // ACTION_CANCEL - gesture was canceled - there will be no more points in it.
+            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+                // Send the events to the device - all pointers are no longer `touching`:
+                sendMotionEvents(true);
+
+                // Clear the state - the gesture has ended.
+                mPrimaryPointerId = null;
+                mPointerIdToData.clear();
+            }
+
+            // ACTION_POINTER_DOWN - new pointer joined the gesture. Its index is passed
+            // through MotionEvent.getActionIndex().
+            if (action == MotionEvent.ACTION_POINTER_DOWN) {
+                int pointerIndex = ev.getActionIndex();
+                int pointerId = ev.getPointerId(pointerIndex);
+
+                if (DEBUG_LOGS) Log.i(TAG, "New pointer, ID=" + pointerId);
+
+                mPointerIdToData.put(pointerId,
+                        new PointerData(ev.getX(pointerIndex), ev.getY(pointerIndex), true));
+
+                if (DEBUG_LOGS) {
+                    Log.i(TAG, "Known pointer IDs after ACTION_POINTER_DOWN:");
+                    for (Map.Entry<Integer, PointerData> entry : mPointerIdToData.entrySet()) {
+                        Log.i(TAG, "ID=" + entry.getKey());
+                    }
+                }
+
+                // Send the events to the device.
+                sendMotionEvents(false);
+            }
+
+            // ACTION_POINTER_UP - pointer left the gesture. Its index is passed though
+            // MotionEvent.getActionIndex().
+            if (action == MotionEvent.ACTION_POINTER_UP) {
+                int pointerIndex = ev.getActionIndex();
+                int pointerId = ev.getPointerId(pointerIndex);
+
+                // Send the events to the device.
+                // The pointer that was raised needs to no longer be `touching`.
+                mPointerIdToData.get(pointerId).touching = false;
+                sendMotionEvents(false);
+
+                // If it so happened that it was a primary pointer, we need to remember that there
+                // is no primary pointer anymore.
+                if (mPrimaryPointerId != null && mPrimaryPointerId == pointerId) {
+                    mPrimaryPointerId = null;
+                }
+                mPointerIdToData.remove(pointerId);
+            }
+
+            if (action == MotionEvent.ACTION_MOVE) {
+                for (int i = 0; i < ev.getPointerCount(); i++) {
+                    int pointerId = ev.getPointerId(i);
+                    PointerData pd = mPointerIdToData.get(pointerId);
+
+                    // If pointer data is null for the given pointer id, then something is wrong
+                    // with the code's assumption - new pointers can only appear due to ACTION_DOWN
+                    // and ACTION_POINTER_DOWN, but it did not seem to happen in this case. If we
+                    // did get null, we want to crash on NullPointerException when accessing data
+                    // below. In case logs are enabled, log this information.
+                    if (DEBUG_LOGS && pd == null) {
+                        Log.i(TAG,
+                                "Pointer with ID " + i
+                                        + " not found in mPointerIdToData. Known pointer IDs:");
+                        for (Map.Entry<Integer, PointerData> entry : mPointerIdToData.entrySet()) {
+                            Log.i(TAG, "ID=" + entry.getKey());
+                        }
+                    }
+
+                    pd.x = ev.getX(i);
+                    pd.y = ev.getY(i);
+                }
+
+                sendMotionEvents(false);
+            }
         }
 
         // We need to consume the touch (returning true) to ensure that we get
@@ -201,6 +329,18 @@
         return true;
     }
 
+    // If the gestureEnded is set to true, the touching state present on the
+    // PointerData entries will be ignored - none of them will be touching and
+    // the entire collection will be cleared anyway.
+    private void sendMotionEvents(boolean gestureEnded) {
+        for (Map.Entry<Integer, PointerData> entry : mPointerIdToData.entrySet()) {
+            mArCoreJavaUtils.onDrawingSurfaceTouch(
+                    mPrimaryPointerId != null && mPrimaryPointerId.equals(entry.getKey()),
+                    gestureEnded ? false : entry.getValue().touching, entry.getKey().intValue(),
+                    entry.getValue().x, entry.getValue().y);
+        }
+    }
+
     @Override // ScreenOrientationDelegate
     public boolean canUnlockOrientation(Activity activity, int defaultOrientation) {
         if (mActivity == activity && mRestoreOrientation != null) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
index 431e8460..89b8d12 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
@@ -33,6 +33,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -130,6 +131,7 @@
      */
     @Test
     @MediumTest
+    @Feature({"StatusBar"})
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     // Customizing status bar color is disallowed for tablets.
@@ -151,6 +153,7 @@
      */
     @Test
     @MediumTest
+    @Feature({"StatusBar"})
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     public void testStatusBarColorNoPageThemeColor() throws ExecutionException, TimeoutException {
@@ -181,6 +184,7 @@
      */
     @Test
     @MediumTest
+    @Feature({"StatusBar"})
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     public void testStatusBarColorCertificateError() throws ExecutionException, TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index d5b3d9851..956c37c3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -873,6 +873,7 @@
      */
     @Test
     @SmallTest
+    @Feature({"StatusBar"})
     @RetryOnFailure
     public void testToolbarColor() {
         Intent intent = createMinimalCustomTabIntent();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/ChromeNightModeTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/ChromeNightModeTestUtils.java
index 9a54c26e..29c5bce 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/ChromeNightModeTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/ChromeNightModeTestUtils.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.night_mode;
 
-import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 
@@ -18,7 +17,6 @@
      * {@link org.chromium.chrome.browser.ChromeActivity} is launched.
      */
     public static void setUpNightModeBeforeChromeActivityLaunched() {
-        CachedFeatureFlags.setNightModeAvailableForTesting(true);
         NightModeUtils.setNightModeSupportedForTesting(true);
     }
 
@@ -36,7 +34,6 @@
      * destroyed.
      */
     public static void tearDownNightModeAfterChromeActivityDestroyed() {
-        CachedFeatureFlags.setNightModeAvailableForTesting(null);
         NightModeUtils.setNightModeSupportedForTesting(null);
         GlobalNightModeStateProviderHolder.resetInstanceForTesting();
         SharedPreferencesManager.getInstance().removeKey(ChromePreferenceKeys.UI_THEME_SETTING);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
index dab5d73..753f35f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.night_mode.settings;
 
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.ANDROID_NIGHT_MODE;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING;
 import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.UI_THEME_DARKEN_WEBSITES_ENABLED;
 import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.UI_THEME_SETTING;
@@ -43,7 +42,6 @@
  * Tests for ThemeSettingsFragment.
  */
 // clang-format off
-@Features.EnableFeatures(ANDROID_NIGHT_MODE)
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 public class ThemeSettingsFragmentTest extends DummyUiActivityTestCase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/share/OWNERS
index f1b7df2..a024badb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/OWNERS
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/OWNERS
@@ -1 +1,5 @@
 file://chrome/android/java/src/org/chromium/chrome/browser/share/OWNERS
+
+per-file ShareButton*=file://components/send_tab_to_self/OWNERS
+per-file ShareDelegate*=file://components/send_tab_to_self/OWNERS
+per-file ShareSheet*=file://components/send_tab_to_self/OWNERS
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java
index 900a458..3ec23c2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java
@@ -86,8 +86,8 @@
         ArrayList<PropertyModel> propertyModels =
                 coordinator.createTopRowPropertyModels(bottomSheet, activity);
         Assert.assertEquals("Incorrect number of property models.", 3, propertyModels.size());
-        Assert.assertEquals("First property model isn't QR Code.",
-                activity.getResources().getString(R.string.qr_code_share_icon_label),
+        Assert.assertEquals("First property model isn't Copy URL.",
+                activity.getResources().getString(R.string.sharing_copy_url),
                 propertyModels.get(0).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("First property model isn't marked as first party.", true,
                 propertyModels.get(0).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
@@ -96,8 +96,8 @@
                 propertyModels.get(1).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("Second property model isn't marked as first party.", true,
                 propertyModels.get(1).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
-        Assert.assertEquals("Third property model isn't Copy URL.",
-                activity.getResources().getString(R.string.sharing_copy_url),
+        Assert.assertEquals("Third property model isn't QR Code.",
+                activity.getResources().getString(R.string.qr_code_share_icon_label),
                 propertyModels.get(2).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("Third property model isn't marked as first party.", true,
                 propertyModels.get(2).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
@@ -115,23 +115,23 @@
         ArrayList<PropertyModel> propertyModels =
                 coordinator.createTopRowPropertyModels(bottomSheet, activity);
         Assert.assertEquals("Incorrect number of property models.", 4, propertyModels.size());
-        Assert.assertEquals("First property model isn't QR Code.",
-                activity.getResources().getString(R.string.qr_code_share_icon_label),
+        Assert.assertEquals("First property model isn't Screenshotz.",
+                activity.getResources().getString(R.string.sharing_screenshot),
                 propertyModels.get(0).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("First property model isn't marked as first party.", true,
                 propertyModels.get(0).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
-        Assert.assertEquals("Second property model isn't SendTabToSelf.",
-                activity.getResources().getString(R.string.send_tab_to_self_share_activity_title),
+        Assert.assertEquals("Second property model isn't Copy URL.",
+                activity.getResources().getString(R.string.sharing_copy_url),
                 propertyModels.get(1).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("Second property model isn't marked as first party.", true,
                 propertyModels.get(1).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
-        Assert.assertEquals("Third property model isn't Copy URL.",
-                activity.getResources().getString(R.string.sharing_copy_url),
+        Assert.assertEquals("Third property model isn't SendTabToSelf.",
+                activity.getResources().getString(R.string.send_tab_to_self_share_activity_title),
                 propertyModels.get(2).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("Third property model isn't marked as first party.", true,
                 propertyModels.get(2).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
-        Assert.assertEquals("Fourth property model isn't Screenshotz.",
-                activity.getResources().getString(R.string.sharing_screenshot),
+        Assert.assertEquals("Fourth property model isn't QR Code.",
+                activity.getResources().getString(R.string.qr_code_share_icon_label),
                 propertyModels.get(3).get(ShareSheetItemViewProperties.LABEL));
         Assert.assertEquals("Fourth property model isn't marked as first party.", true,
                 propertyModels.get(3).get(ShareSheetItemViewProperties.IS_FIRST_PARTY));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java
index 5393b6b..8625dfd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java
@@ -124,7 +124,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testNoBrandColor() {
         startMainActivityWithURL(getUrlWithBrandColor(""));
         checkForBrandColor(mDefaultColor);
@@ -136,7 +136,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testBrandColorNoAlpha() {
         startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1));
         checkForBrandColor(Color.parseColor(BRAND_COLOR_1));
@@ -148,7 +148,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testImmediateColorChange() {
         startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1));
         checkForBrandColor(Color.parseColor(BRAND_COLOR_1));
@@ -169,7 +169,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testBrandColorWithLoadStarted() {
         startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1));
         PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
@@ -188,7 +188,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testNavigatingToNewBrandColor() {
         startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1));
         checkForBrandColor(Color.parseColor(BRAND_COLOR_1));
@@ -203,7 +203,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testNavigatingToBrandColorAndBack() {
         startMainActivityWithURL("about:blank");
         checkForBrandColor(mDefaultColor);
@@ -228,7 +228,7 @@
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
     @DisableInTabbedMode
-    @Feature({"Omnibox"})
+    @Feature({"StatusBar", "Omnibox"})
     public void testBrandColorInterstitial() {
         final String brandColorUrl = getUrlWithBrandColor(BRAND_COLOR_1);
         startMainActivityWithURL(brandColorUrl);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
new file mode 100644
index 0000000..bbcb643
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
@@ -0,0 +1,110 @@
+// 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.ui.system;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.os.Build;
+import android.support.test.filters.LargeTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.MinAndroidSdkLevel;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.tab.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.util.browser.ThemeTestUtils;
+import org.chromium.components.browser_ui.styles.ChromeColors;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+/**
+ * {@link StatusBarColorController} tests.
+ * There are additional status bar color tests in {@link BrandColorTest}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class StatusBarColorControllerTest {
+    @Rule
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+
+    @Before
+    public void setUp() {
+        CachedFeatureFlags.setGridTabSwitcherEnabledForTesting(true);
+        mActivityTestRule.startMainActivityOnBlankPage();
+    }
+
+    @After
+    public void tearDown() {
+        CachedFeatureFlags.setGridTabSwitcherEnabledForTesting(null);
+    }
+
+    /**
+     * Test that the status bar color is toggled when toggling incognito while in overview mode.
+     */
+    @Test
+    @LargeTest
+    @Feature({"StatusBar"})
+    @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
+    public void testColorToggleIncongitoInOverview() {
+        ChromeTabbedActivity activity = mActivityTestRule.getActivity();
+        Resources resources = activity.getResources();
+        final int expectedOverviewStandardColor = defaultColorFallbackToBlack(
+                ChromeColors.getPrimaryBackgroundColor(resources, false));
+        final int expectedOverviewIncognitoColor = defaultColorFallbackToBlack(
+                ChromeColors.getPrimaryBackgroundColor(resources, true));
+
+        mActivityTestRule.loadUrlInNewTab(
+                "about:blank", true /* incognito */, TabLaunchType.FROM_CHROME_UI);
+        TabModelSelector tabModelSelector = activity.getTabModelSelector();
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { tabModelSelector.selectModel(true /* incongito */); });
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { activity.getLayoutManager().showOverview(false /* animate */); });
+
+        ThemeTestUtils.assertStatusBarColor(activity, expectedOverviewIncognitoColor);
+
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { tabModelSelector.selectModel(false /* incongito */); });
+        ThemeTestUtils.assertStatusBarColor(activity, expectedOverviewStandardColor);
+    }
+
+    /**
+     * Test that the default color (and not the active tab's brand color) is used in overview mode.
+     */
+    @Test
+    @LargeTest
+    @Feature({"StatusBar"})
+    @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
+    public void testBrandColorIgnoredInOverview() throws Exception {
+        ChromeTabbedActivity activity = mActivityTestRule.getActivity();
+        Resources resources = activity.getResources();
+        final int expectedDefaultStandardColor =
+                defaultColorFallbackToBlack(ChromeColors.getDefaultThemeColor(resources, false));
+
+        String pageWithBrandColorUrl = mActivityTestRule.getTestServer().getURL(
+                "/chrome/test/data/android/theme_color_test.html");
+        mActivityTestRule.loadUrl(pageWithBrandColorUrl);
+        ThemeTestUtils.waitForThemeColor(activity, Color.RED);
+        ThemeTestUtils.assertStatusBarColor(activity, Color.RED);
+
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { activity.getLayoutManager().showOverview(false /* animate */); });
+        ThemeTestUtils.assertStatusBarColor(activity, expectedDefaultStandardColor);
+    }
+
+    private int defaultColorFallbackToBlack(int color) {
+        return (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? Color.BLACK : color;
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
index fc6c9df..971b7219 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -81,7 +81,7 @@
 
     @Test
     @SmallTest
-    @Feature({"Webapps"})
+    @Feature({"StatusBar", "Webapps"})
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
     public void testThemeColorWhenNotSpecified() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
index 3dd4d95..f9b061e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
@@ -40,7 +40,7 @@
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     // Customizing status bar color is disallowed for tablets.
-    @Feature({"Webapps"})
+    @Feature({"StatusBar", "Webapps"})
     public void testThemeColorWhenSpecified() {
         // This is Color.Magenta with 50% opacity.
         final int intentThemeColor = Color.argb(0x80, 0xFF, 0, 0xFF);
@@ -57,7 +57,7 @@
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1)
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     // Customizing status bar color is disallowed for tablets.
-    @Feature({"Webapps"})
+    @Feature({"StatusBar", "Webapps"})
     public void testThemeColorNotUsedIfPagesHasOne() throws ExecutionException, TimeoutException {
         final int intentThemeColor = Color.MAGENTA;
         final int pageThemeColor = Color.RED;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java
index d9c1e89d..ad92ef0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java
@@ -15,7 +15,6 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 
 /**
@@ -26,14 +25,14 @@
 public class GlobalNightModeStateProviderHolderTest {
     @After
     public void tearDown() {
-        CachedFeatureFlags.setNightModeAvailableForTesting(null);
         GlobalNightModeStateProviderHolder.resetInstanceForTesting();
+        NightModeUtils.setNightModeSupportedForTesting(null);
         SharedPreferencesManager.getInstance().removeKey(UI_THEME_SETTING);
     }
 
     @Test
     public void testNightModeNotAvailable() {
-        CachedFeatureFlags.setNightModeAvailableForTesting(false);
+        NightModeUtils.setNightModeSupportedForTesting(false);
 
         // Verify that night mode is disabled.
         assertFalse(GlobalNightModeStateProviderHolder.getInstance().isInNightMode());
@@ -47,7 +46,6 @@
     public void testNightModeAvailable() {
         // Verify that the instance is a GlobalNightModeStateController. Other tests are covered
         // in GlobalNightModeStateControllerTest.java.
-        CachedFeatureFlags.setNightModeAvailableForTesting(true);
         assertTrue(GlobalNightModeStateProviderHolder.getInstance()
                            instanceof GlobalNightModeStateController);
     }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 1bb728f..5ced73c 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1744,6 +1744,10 @@
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is mixed-content.">
         This file can't be downloaded securely.
       </message>
+      <message name="IDS_BLOCK_REASON_DEEP_SCANNING"
+        desc="Message shown on chrome://downloads when a download is being scanned">
+        This file is being scanned.
+      </message>
       <message name="IDS_DEEP_SCANNED_SAFE_DESCRIPTION"
         desc="Message shown to the user on chrome://downloads page to explain this this download was deep scanned, and found to be safe.">
         Scan complete, no issues identified.
diff --git a/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_DEEP_SCANNING.png.sha1 b/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_DEEP_SCANNING.png.sha1
new file mode 100644
index 0000000..4821424
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_DEEP_SCANNING.png.sha1
@@ -0,0 +1 @@
+7e5cb61f27a35050f60a77f0dcf622a0b9c62551
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index fc09c47..3b0f651 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -1470,5 +1470,129 @@
   <message name="IDS_SETTINGS_USER_EXISTS_ERROR" desc="Error message for attempting to add a user that already exists">
     This user already exists
   </message>
+  
+  <!-- Multidevice Page (OS settings) -->
+  <message name="IDS_SETTINGS_MULTIDEVICE" desc="Title of a section of settings. This section describes settings for devices that are connected to the Chromebook, like phones.">
+    Connected devices
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_BUTTON" desc="Label of the button that opens a menu to the user that allows them to set up a connection between the user's phone and their Chromebook to give them access to special features.">
+    Set up
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_VERIFY_BUTTON" desc="Label for the button to get the Chromebook to verify that it can connect with their phone.">
+    Verify
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_ITEM_HEADING" desc="Heading for settings item that allows the user to connect their phone to their Chromebook.">
+    Android phone
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_ENABLED" desc="Text to tell user multidevice features are turned on">
+    Enabled
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_DISABLED" desc="Text to tell user multidevice features are turned off">
+    Disabled
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING" desc="Name of a feature. This feature automatically offers the user to tether to their phone if their Chromebook is offline and their phone supports tethering.">
+    Instant Tethering
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING_SUMMARY" desc="Description of for the 'Instant Tethering' setting. This feature automatically offers the user to tether to their phone if their Chromebook is offline and their phone supports tethering.">
+    Connect to the internet through your phone
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES" desc="Name of a feature. This feature lets the user read and reply to text messages from their Chromebook. New text messages will appear as notifications.">
+    Messages
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY" desc="Description of for the 'Android Messages' setting. This feature lets the user read and reply to text messages from their Chromebook. New text messages will appear as notifications.">
+    Send and receive text messages from your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$2<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
+  </message>
+
+  <!-- Lock Screen Page (OS settings) -->
+  <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_TITLE" desc="The title of options to change the behavior of notifications on the lock screen.">
+    On the lock screen
+  </message>
+  <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE_SENSITIVE" desc="One of options of the lock screen notification mode to hide sensitive contents and show the others on the lock screen.">
+    Hide sensitive content
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_ENABLE_SCREENLOCK" desc="The text on the checkbox to enable screenlocker for current user.">
+    Show lock screen when waking from sleep
+  </message>
+  <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW" desc="One of options of the lock screen notification mode to show all the notifications and its contents on the lock screen.">
+    Show all notification content
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_PASSWORD" desc="The account password or a custom PIN can be used to unlock the device.">
+    PIN or password
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SETUP_BUTTON" desc="Text on the lock screen button which opens up the fingerprint subpage.">
+    Set up
+  </message>
+  <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE" desc="One of options of the lock screen notification mode to hide all the notifications on the lock screen.">
+    Don't show notifications at all
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS" desc="Text on the lock screen which opens up the fingerprint subpage.">
+    Edit Fingerprints
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS_DESCRIPTION" desc="Secondary text on the lock screen which opens up the fingerprint subpage.">
+    Set up a faster way to unlock your device
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_ONLY" desc="Only the account password can be used to unlock the device.">
+    Password only
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PIN_BUTTON" desc="Button that the user can click to change an existing already-active PIN.">
+    Change PIN
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NUM_FINGERPRINTS" desc="Text on the lock screen which tells users how many fingerprints they have enrolled.">
+    <ph name="NUM_FINGERPRINTS">$1<ex>1</ex></ph> fingerprints set up
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NONE" desc="Text on the people page which notifies the user that the device will not show lock screen or prompt for auth after waking from sleep.">
+    Sign in automatically
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME" desc="The default name (plus a number for a newly added fingerprint).">
+    Finger <ph name="NEW_FINGER_NUMBER">$1<ex>1</ex></ph>
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_DELETE_FINGERPRINT_ARIA_LABEL" desc="Aria label for the button in the fingerprint subpage that deletes a registered fingerprint. Only visible by screen reader software.">
+    delete [<ph name="FINGERPRINT_NAME">$1<ex>Fingerprint 1</ex></ph>]
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK" desc="Text on the lock screen which is the subheader for the screen locking options.">
+    Screen lock options
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE" desc="Header to tell the user an action will make their Chromebook forget their phone. This means they will no longer have access to multidevice features.">
+    Forget phone
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION" desc="Explanation on a clickable menu item that makes the Chromebook forget the user's phone. It tells the user that the menu item will cause their phone to stop acting as a partner for their Chromebook for multidevice features.">
+    Disconnect your phone from your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE" desc="Text of a dialog that lets the user choose if their Chromebook should forget their phone. This means they will no longer have access to multidevice features.">
+    Disconnect your phone from your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. They will no longer connect automatically.
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_DISCONNECT" desc="Text for the button that lets the user choose if their Chromebook should forget their phone. This means they will no longer have access to multidevice features.">
+    Disconnect
+  </message>
+    <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY" desc="Tells the user to connect their Chromebook to their phone.">
+    Connect your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> with your phone. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$2<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_NO_ELIGIBLE_HOSTS" desc="Tells the user that there is no phone with their account on it that can connect to their Chromebook.">
+    No eligible devices. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$1<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_VERIFICATION_TEXT" desc="Text to tell user that their Chromebook needs to verify that it can connect with their phone.">
+    Waiting for verification. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$1<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_SMART_LOCK_SUMMARY" desc="Description of for the 'Smart Lock' setting. This feature automatically unlocks the user's Chromebook if their phone is nearby and unlocked.">
+    Unlock your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> with your phone. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$2<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOGIN_LOCK" desc="Text on the lock screen which is the subheader for the screen locking options.">
+    Lock screen from sleep mode
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SETUP_PIN_BUTTON" desc="Button that is used to setup a new PIN when the user does not have a PIN yet.">
+    Set up PIN
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOCK" desc="Text on the people page which opens up the quick unlock subpage and the title of the quick unlock subpage.">
+    Screen lock
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK" desc="Text on the people page which opens up the security and sign-in section.">
+    Security and sign-in
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure these settings.">
+    Enter your password to configure screen lock
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure security and sign-in settings.">
+    Enter your password to configure security and sign-in
+  </message>
 </if>
 </grit-part>
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 45d2c40c..1cb55c6 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2632,6 +2632,15 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_PERMISSIONS" desc="The Permissions header, used to group together permissions, such as Geolocation, on the Site Details page.">
     Permissions
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_PERMISSIONS_MORE" desc="The text on the button used to toggle the display of additional permission settings.">
+    Additional permissions
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_CONTENT" desc="The Content header, used to group together website content settings, such as Cookies and JavaScript on the Site Details page.">
+    Content
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_CONTENT_MORE" desc="The text on the button used to toggle the display of additional content settings.">
+    Additional content settings
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_SOURCE_DRM_DISABLED" desc="A label shown when the protected content / protected media identifier permission on the Site Details page is disabled because the user has turned off using unique identifiers to access protected content.">
     To change this setting, first <ph name="BEGIN_LINK">&lt;a target="_blank" href="$1"&gt;</ph>turn on identifiers<ph name="END_LINK">&lt;/a&gt;</ph>
   </message>
@@ -2970,48 +2979,6 @@
     <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED" desc="Message shown below the title that tells the user they have entered two different PIN values.">
       PINs do not match
     </message>
-    <message name="IDS_SETTINGS_PEOPLE_ENABLE_SCREENLOCK" desc="The text on the checkbox to enable screenlocker for current user.">
-      Show lock screen when waking from sleep
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOCK" desc="Text on the people page which opens up the quick unlock subpage and the title of the quick unlock subpage.">
-      Screen lock
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK" desc="Text on the people page which opens up the security and sign-in section.">
-      Security and sign-in
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK" desc="Text on the lock screen which is the subheader for the screen locking options.">
-      Screen lock options
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOGIN_LOCK" desc="Text on the lock screen which is the subheader for the screen locking options.">
-      Lock screen from sleep mode
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_ONLY" desc="Only the account password can be used to unlock the device.">
-      Password only
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_PASSWORD" desc="The account password or a custom PIN can be used to unlock the device.">
-      PIN or password
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NONE" desc="Text on the people page which notifies the user that the device will not show lock screen or prompt for auth after waking from sleep.">
-      Sign in automatically
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PIN_BUTTON" desc="Button that the user can click to change an existing already-active PIN.">
-      Change PIN
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SETUP_PIN_BUTTON" desc="Button that is used to setup a new PIN when the user does not have a PIN yet.">
-      Set up PIN
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS" desc="Text on the lock screen which opens up the fingerprint subpage.">
-      Edit Fingerprints
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS_DESCRIPTION" desc="Secondary text on the lock screen which opens up the fingerprint subpage.">
-      Set up a faster way to unlock your device
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SETUP_BUTTON" desc="Text on the lock screen button which opens up the fingerprint subpage.">
-      Set up
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NUM_FINGERPRINTS" desc="Text on the lock screen which tells users how many fingerprints they have enrolled.">
-      <ph name="NUM_FINGERPRINTS">$1<ex>1</ex></ph> fingerprints set up
-    </message>
     <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SUBPAGE_TITLE" desc="Title of the fingerprint subpage.">
       Fingerprint
     </message>
@@ -3024,12 +2991,6 @@
     <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_LESS_SECURE" desc="Text telling users that fingerprints might be less secure than strong PINs or passwords.">
       Note: Your fingerprint may be less secure than a strong password or PIN.
     </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_DELETE_FINGERPRINT_ARIA_LABEL" desc="Aria label for the button in the fingerprint subpage that deletes a registered fingerprint. Only visible by screen reader software.">
-      delete [<ph name="FINGERPRINT_NAME">$1<ex>Fingerprint 1</ex></ph>]
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME" desc="The default name (plus a number for a newly added fingerprint).">
-      Finger <ph name="NEW_FINGER_NUMBER">$1<ex>1</ex></ph>
-    </message>
     <message name="IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE" desc="Title of Account Manager Settings page.">
       My accounts
     </message>
@@ -3042,14 +3003,12 @@
     <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE" desc="Title of the add fingerprint dialog popup.">
       Set up your fingerprint
     </message>
-
     <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON" desc="Text in the add fingerprint dialog telling users to place finger on the power button which is the sensor.">
       Touch the power button with your finger
     </message>
      <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON_ARIA_LABEL" desc="Aria label in the add fingerprint dialog telling users that the fingerprint sensor is in the power button. Only visible by screen reader software.">
       The fingerprint sensor is in the power button. Touch it lightly with any finger.
     </message>
-
     <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD" desc="Text in the add fingerprint dialog telling users to place finger on the sensor on the keyboard.">
       Touch the fingerprint sensor with your finger
     </message>
@@ -3062,7 +3021,6 @@
      <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_TOP_RIGHT_ARIA_LABEL" desc="Aria label in the add fingerprint dialog telling users that the fingerprint sensor is in the top right corner of the keyboard. Only visible by screen reader software.">
       The fingerprint sensor is the top right-hand key on your keyboard. Touch it lightly with any finger.
     </message>
-
     <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_READY" desc="Text in the add fingerprint dialog that confirms user's fingerprint scan was successful.">
       Fingerprint added.
     </message>
@@ -3081,12 +3039,6 @@
     <message name="IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_ADD_ANOTHER_BUTTON" desc="Text on the button in the fingerprint setup dialog which allows users to add another fingerprint once a fingerprint has been setup.">
       Add another
     </message>
-    <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure these settings.">
-      Enter your password to configure screen lock
-    </message>
-    <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure security and sign-in settings.">
-      Enter your password to configure security and sign-in
-    </message>
     <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_PASSWORD_LABEL" desc="An input box label that tells the user to enter their password in that input box.">
       Password
     </message>
@@ -3717,64 +3669,6 @@
     </message>
   </if>
 
-  <!-- Multidevice Page -->
-  <if expr="chromeos">
-    <message name="IDS_SETTINGS_MULTIDEVICE" desc="Title of a section of settings. This section describes settings for devices that are connected to the Chromebook, like phones.">
-      Connected devices
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_ITEM_HEADING" desc="Heading for settings item that allows the user to connect their phone to their Chromebook.">
-      Android phone
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY" desc="Tells the user to connect their Chromebook to their phone.">
-      Connect your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> with your phone. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$2<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_NO_ELIGIBLE_HOSTS" desc="Tells the user that there is no phone with their account on it that can connect to their Chromebook.">
-      No eligible devices. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$1<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_VERIFICATION_TEXT" desc="Text to tell user that their Chromebook needs to verify that it can connect with their phone.">
-      Waiting for verification. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$1<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_BUTTON" desc="Label of the button that opens a menu to the user that allows them to set up a connection between the user's phone and their Chromebook to give them access to special features.">
-      Set up
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_VERIFY_BUTTON" desc="Label for the button to get the Chromebook to verify that it can connect with their phone.">
-      Verify
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_ENABLED" desc="Text to tell user multidevice features are turned on">
-      Enabled
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_DISABLED" desc="Text to tell user multidevice features are turned off">
-      Disabled
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_SMART_LOCK_SUMMARY" desc="Description of for the 'Smart Lock' setting. This feature automatically unlocks the user's Chromebook if their phone is nearby and unlocked.">
-      Unlock your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> with your phone. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$2<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING" desc="Name of a feature. This feature automatically offers the user to tether to their phone if their Chromebook is offline and their phone supports tethering.">
-      Instant Tethering
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING_SUMMARY" desc="Description of for the 'Instant Tethering' setting. This feature automatically offers the user to tether to their phone if their Chromebook is offline and their phone supports tethering.">
-      Connect to the internet through your phone
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES" desc="Name of a feature. This feature lets the user read and reply to text messages from their Chromebook. New text messages will appear as notifications.">
-      Messages
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY" desc="Description of for the 'Android Messages' setting. This feature lets the user read and reply to text messages from their Chromebook. New text messages will appear as notifications.">
-      Send and receive text messages from your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. <ph name="LINK_BEGIN">&lt;a target="_blank" href="$2<ex>https://google.com/</ex>"&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE" desc="Header to tell the user an action will make their Chromebook forget their phone. This means they will no longer have access to multidevice features.">
-      Forget phone
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION" desc="Explanation on a clickable menu item that makes the Chromebook forget the user's phone. It tells the user that the menu item will cause their phone to stop acting as a partner for their Chromebook for multidevice features.">
-      Disconnect your phone from your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE" desc="Text of a dialog that lets the user choose if their Chromebook should forget their phone. This means they will no longer have access to multidevice features.">
-      Disconnect your phone from your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. They will no longer connect automatically.
-    </message>
-    <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_DISCONNECT" desc="Text for the button that lets the user choose if their Chromebook should forget their phone. This means they will no longer have access to multidevice features.">
-      Disconnect
-    </message>
-  </if>
-
   <!-- Password protection -->
   <message name="IDS_SETTINGS_CHANGE_PASSWORD_TITLE" desc="Title of the reset password warning.">
     Your password may be compromised
@@ -3934,21 +3828,6 @@
     <ph name="PAGE_NAME">$1<ex>Bookmarks</ex></ph> is not available to Guest users.
   </message>
 
-  <if expr="chromeos">
-    <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_TITLE" desc="The title of options to change the behavior of notifications on the lock screen.">
-      On the lock screen
-    </message>
-    <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW" desc="One of options of the lock screen notification mode to show all the notifications and its contents on the lock screen.">
-      Show all notification content
-    </message>
-    <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE" desc="One of options of the lock screen notification mode to hide all the notifications on the lock screen.">
-      Don't show notifications at all
-    </message>
-    <message name="IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE_SENSITIVE" desc="One of options of the lock screen notification mode to hide sensitive contents and show the others on the lock screen.">
-      Hide sensitive content
-    </message>
-  </if>
-
   <!-- Security Keys -->
   <message name="IDS_SETTINGS_SECURITY_KEYS_TITLE" desc="Headline in the Settings UI for the subpage handling security keys. Security keys are external physcial devices for user authentication and the translation should match that used in, for example, IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION.">
     Manage security keys
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc
index dde3a09..f86c8660 100644
--- a/chrome/browser/android/shortcut_helper.cc
+++ b/chrome/browser/android/shortcut_helper.cc
@@ -155,14 +155,12 @@
 std::unique_ptr<ShortcutInfo> ShortcutHelper::CreateShortcutInfo(
     const GURL& manifest_url,
     const blink::Manifest& manifest,
-    const GURL& primary_icon_url,
-    const GURL& badge_icon_url) {
+    const GURL& primary_icon_url) {
   auto shortcut_info = std::make_unique<ShortcutInfo>(GURL());
   if (!manifest.IsEmpty()) {
     shortcut_info->UpdateFromManifest(manifest);
     shortcut_info->manifest_url = manifest_url;
     shortcut_info->best_primary_icon_url = primary_icon_url;
-    shortcut_info->best_badge_icon_url = badge_icon_url;
   }
 
   shortcut_info->ideal_splash_image_size_in_px = GetIdealSplashImageSizeInPx();
diff --git a/chrome/browser/android/shortcut_helper.h b/chrome/browser/android/shortcut_helper.h
index b8ed8d4a..2e80d74 100644
--- a/chrome/browser/android/shortcut_helper.h
+++ b/chrome/browser/android/shortcut_helper.h
@@ -32,8 +32,7 @@
   static std::unique_ptr<ShortcutInfo> CreateShortcutInfo(
       const GURL& manifest_url,
       const blink::Manifest& manifest,
-      const GURL& primary_icon_url,
-      const GURL& badge_icon_url);
+      const GURL& primary_icon_url);
 
   // Adds a shortcut to the launcher using a SkBitmap. The type of shortcut
   // added depends on the properties in |info|.
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.cc b/chrome/browser/android/vr/arcore_device/arcore_device.cc
index c52c376e..e80cc88 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.cc
@@ -184,9 +184,12 @@
   RequestArCoreGlInitialization(window, rotation, frame_size);
 }
 
-void ArCoreDevice::OnDrawingSurfaceTouch(bool touching,
+void ArCoreDevice::OnDrawingSurfaceTouch(bool is_primary,
+                                         bool touching,
+                                         int32_t pointer_id,
                                          const gfx::PointF& location) {
-  DVLOG(2) << __func__ << ": touching=" << touching;
+  DVLOG(2) << __func__ << ": pointer_id=" << pointer_id
+           << " is_primary=" << is_primary << " touching=" << touching;
 
   if (!session_state_->is_arcore_gl_initialized_ ||
       !session_state_->arcore_gl_thread_)
@@ -194,8 +197,8 @@
 
   PostTaskToGlThread(base::BindOnce(
       &ArCoreGl::OnScreenTouch,
-      session_state_->arcore_gl_thread_->GetArCoreGl()->GetWeakPtr(), touching,
-      location));
+      session_state_->arcore_gl_thread_->GetArCoreGl()->GetWeakPtr(),
+      is_primary, touching, pointer_id, location));
 }
 
 void ArCoreDevice::OnDrawingSurfaceDestroyed() {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.h b/chrome/browser/android/vr/arcore_device/arcore_device.h
index a116598..5005878a 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.h
@@ -57,7 +57,10 @@
   void OnDrawingSurfaceReady(gfx::AcceleratedWidget window,
                              display::Display::Rotation rotation,
                              const gfx::Size& frame_size);
-  void OnDrawingSurfaceTouch(bool touching, const gfx::PointF& location);
+  void OnDrawingSurfaceTouch(bool is_primary,
+                             bool touching,
+                             int32_t pointer_id,
+                             const gfx::PointF& location);
   void OnDrawingSurfaceDestroyed();
   void OnSessionEnded();
 
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.cc b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
index 8e31039..6040d31c 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
@@ -46,8 +46,6 @@
 constexpr std::array<float, 6> kDisplayCoordinatesForTransform = {
     0.f, 0.f, 1.f, 0.f, 0.f, 1.f};
 
-constexpr uint32_t kInputSourceId = 1;
-
 const char kInputSourceProfileName[] = "generic-touchscreen";
 
 gfx::Transform ConvertUvsToTransformMatrix(const std::vector<float>& uvs) {
@@ -641,12 +639,12 @@
   // check if we recognize the input source id.
 
   if (native_origin_information->is_input_source_id()) {
-    if (native_origin_information->get_input_source_id() != kInputSourceId) {
-      DVLOG(1) << __func__ << ": incorrect input source ID passed";
-      std::move(callback).Run(
-          device::mojom::SubscribeToHitTestResult::FAILURE_GENERIC, 0);
-      return;
-    }
+    DVLOG(1) << __func__
+             << ": ARCore device supports only transient input sources for "
+                "now. Rejecting subscription request.";
+    std::move(callback).Run(
+        device::mojom::SubscribeToHitTestResult::FAILURE_GENERIC, 0);
+    return;
   }
 
   base::Optional<uint64_t> maybe_subscription_id = arcore_->SubscribeToHitTest(
@@ -759,11 +757,7 @@
   DCHECK(is_initialized_);
 
   if (frame_data->pose) {
-    mojom::XRInputSourceStatePtr input_state = GetInputSourceState();
-    if (input_state) {
-      input_states_.push_back(std::move(input_state));
-      frame_data->input_state = std::move(input_states_);
-    }
+    frame_data->input_state = GetInputSourceStates();
 
     // Get results for hit test subscriptions.
     frame_data->hit_test_subscription_results =
@@ -787,117 +781,199 @@
   std::move(callback).Run(std::move(frame_data));
 }
 
-void ArCoreGl::OnScreenTouch(bool touching, const gfx::PointF& touch_point) {
-  DVLOG(2) << __func__ << ": touching=" << touching;
-  screen_last_touch_ = touch_point;
-  screen_touch_active_ = touching;
-  if (touching)
-    screen_touch_pending_ = true;
-}
+void ArCoreGl::OnScreenTouch(bool is_primary,
+                             bool touching,
+                             int32_t pointer_id,
+                             const gfx::PointF& touch_point) {
+  DVLOG(2) << __func__ << ": is_primary=" << is_primary
+           << ", pointer_id=" << pointer_id << ", touching=" << touching
+           << ", touch_point=" << touch_point.ToString();
 
-mojom::XRInputSourceStatePtr ArCoreGl::GetInputSourceState() {
-  DVLOG(3) << __func__;
+  if (!base::Contains(pointer_id_to_input_source_id_, pointer_id)) {
+    // assign ID
+    DCHECK(next_input_source_id_ != 0) << "ID equal to 0 cannot be used!";
+    pointer_id_to_input_source_id_[pointer_id] = next_input_source_id_;
 
-  // If there's no active screen touch, and no unreported past click event,
-  // don't report a device.
-  if (!screen_touch_pending_ && !screen_touch_active_)
-    return nullptr;
+    DVLOG(3)
+        << __func__
+        << " : pointer id not previously recognized, assigned input source id="
+        << next_input_source_id_;
 
-  device::mojom::XRInputSourceStatePtr state =
-      device::mojom::XRInputSourceState::New();
-
-  // Only one controller is supported, so the source id can be static.
-  state->source_id = kInputSourceId;
-
-  state->primary_input_pressed = screen_touch_active_;
-  if (!screen_touch_active_ && screen_touch_pending_) {
-    state->primary_input_clicked = true;
-    screen_touch_pending_ = false;
+    // Overflow is defined behavior for unsigned integers, just make sure that
+    // we never send out ID = 0.
+    next_input_source_id_++;
+    if (next_input_source_id_ == 0) {
+      next_input_source_id_ = 1;
+    }
   }
 
-  // Save the touch point for use in Blink's XR input event deduplication.
-  state->overlay_pointer_position = base::make_optional<gfx::PointF>(
-      screen_last_touch_.x(), screen_last_touch_.y());
+  uint32_t inputSourceId = pointer_id_to_input_source_id_[pointer_id];
+  ScreenTouchEvent& screen_touch_event = screen_touch_events_[inputSourceId];
 
-  state->description = device::mojom::XRInputSourceDescription::New();
+  screen_touch_event.pointer_id = pointer_id;
+  screen_touch_event.is_primary = is_primary;
+  screen_touch_event.screen_last_touch = touch_point;
+  screen_touch_event.screen_touch_active = touching;
+  if (touching) {
+    screen_touch_event.screen_touch_pending = true;
+  }
+}
 
-  state->description->handedness = device::mojom::XRHandedness::NONE;
+std::vector<mojom::XRInputSourceStatePtr> ArCoreGl::GetInputSourceStates() {
+  DVLOG(3) << __func__;
 
-  state->description->target_ray_mode = device::mojom::XRTargetRayMode::TAPPING;
+  std::vector<mojom::XRInputSourceStatePtr> result;
 
-  state->description->profiles.push_back(kInputSourceProfileName);
+  for (auto& id_and_touch_event : screen_touch_events_) {
+    bool is_primary = id_and_touch_event.second.is_primary;
+    bool screen_touch_pending = id_and_touch_event.second.screen_touch_pending;
+    bool screen_touch_active = id_and_touch_event.second.screen_touch_active;
+    gfx::PointF screen_last_touch = id_and_touch_event.second.screen_last_touch;
 
-  // Controller doesn't have a measured position.
-  state->emulated_position = true;
+    // TODO(https://crbug.com/1048329): For now, we are ignoring non-primary
+    // pointers to maintain previous behavior. Once mojo changes, send out the
+    // non-primary pointer information as well.
+    if (!is_primary) {
+      DVLOG(3) << __func__
+               << " : pointer for input source id=" << id_and_touch_event.first
+               << " not considered primary, ignoring. pointer_id="
+               << id_and_touch_event.second.pointer_id;
+      continue;
+    }
 
-  // The Renderer code ignores state->grip for TAPPING (screen-based) target ray
-  // mode, so we don't bother filling it in here. If this does get used at
-  // some point in the future, this should be set to the inverse of the
-  // pose rigid transform.
+    DVLOG(3) << __func__
+             << " : pointer for input source id=" << id_and_touch_event.first
+             << ", pointer_id=" << id_and_touch_event.second.pointer_id
+             << ", active=" << screen_touch_active
+             << ", pending=" << screen_touch_pending;
 
-  // Get a viewer-space ray from screen-space coordinates by applying the
-  // inverse of the projection matrix. Z coordinate of -1 means the point will
-  // be projected onto the projection matrix near plane. See also
-  // third_party/blink/renderer/modules/xr/xr_view.cc's UnprojectPointer.
-  const float x_normalized =
-      screen_last_touch_.x() / transfer_size_.width() * 2.f - 1.f;
-  const float y_normalized =
-      (1.f - screen_last_touch_.y() / transfer_size_.height()) * 2.f - 1.f;
-  gfx::Point3F touch_point(x_normalized, y_normalized, -1.f);
-  DVLOG(3) << __func__ << ": touch_point=" << touch_point.ToString();
-  inverse_projection_.TransformPoint(&touch_point);
-  DVLOG(3) << __func__ << ": unprojected=" << touch_point.ToString();
+    // If there's no active screen touch, and no unreported past click
+    // event, don't report a device.
+    if (!screen_touch_pending && !screen_touch_active) {
+      continue;
+    }
 
-  // Ray points along -Z in ray space, so we need to flip it to get
-  // the +Z axis unit vector.
-  gfx::Vector3dF ray_backwards(-touch_point.x(), -touch_point.y(),
-                               -touch_point.z());
-  gfx::Vector3dF new_z;
-  bool can_normalize = ray_backwards.GetNormalized(&new_z);
-  DCHECK(can_normalize);
+    device::mojom::XRInputSourceStatePtr state =
+        device::mojom::XRInputSourceState::New();
 
-  // Complete the ray-space basis by adding X and Y unit
-  // vectors based on cross products.
-  const gfx::Vector3dF kUp(0.f, 1.f, 0.f);
-  gfx::Vector3dF new_x(kUp);
-  new_x.Cross(new_z);
-  new_x.GetNormalized(&new_x);
-  gfx::Vector3dF new_y(new_z);
-  new_y.Cross(new_x);
-  new_y.GetNormalized(&new_y);
+    state->source_id = id_and_touch_event.first;
 
-  // Fill in the transform matrix in row-major order. The first three columns
-  // contain the basis vectors, the fourth column the position offset.
-  gfx::Transform viewer_from_pointer(
-      new_x.x(), new_y.x(), new_z.x(), touch_point.x(),  // row 1
-      new_x.y(), new_y.y(), new_z.y(), touch_point.y(),  // row 2
-      new_x.z(), new_y.z(), new_z.z(), touch_point.z(),  // row 3
-      0, 0, 0, 1);
-  DVLOG(3) << __func__ << ": viewer_from_pointer=\n"
-           << viewer_from_pointer.ToString();
+    state->primary_input_pressed = screen_touch_active;
 
-  state->description->input_from_pointer = viewer_from_pointer;
+    // If the touch is not active but pending, it means that it was clicked
+    // within a single frame.
+    if (!screen_touch_active && screen_touch_pending) {
+      state->primary_input_clicked = true;
 
-  // Create the gamepad object and modify necessary fields.
-  state->gamepad = device::Gamepad{};
-  state->gamepad->connected = true;
-  state->gamepad->id[0] = '\0';
-  state->gamepad->timestamp =
-      base::TimeTicks::Now().since_origin().InMicroseconds();
+      // Clear screen_touch_pending for this input source - we have consumed it.
+      id_and_touch_event.second.screen_touch_pending = false;
+    }
 
-  state->gamepad->axes_length = 2;
-  state->gamepad->axes[0] = x_normalized;
-  state->gamepad->axes[1] = -y_normalized;  //  Gamepad's Y axis is actually
-                                            //  inverted (1.0 means "backward").
+    // Save the touch point for use in Blink's XR input event deduplication.
+    state->overlay_pointer_position = screen_last_touch;
 
-  state->gamepad->buttons_length = 3;  // 2 placeholders + the real one
-  // Default-constructed buttons are already valid placeholders.
-  state->gamepad->buttons[2].touched = true;
-  state->gamepad->buttons[2].value = 1.0;
-  state->gamepad->mapping = device::GamepadMapping::kNone;
-  state->gamepad->hand = device::GamepadHand::kNone;
+    state->description = device::mojom::XRInputSourceDescription::New();
 
-  return state;
+    state->description->handedness = device::mojom::XRHandedness::NONE;
+
+    state->description->target_ray_mode =
+        device::mojom::XRTargetRayMode::TAPPING;
+
+    state->description->profiles.push_back(kInputSourceProfileName);
+
+    // Controller doesn't have a measured position.
+    state->emulated_position = true;
+
+    // The Renderer code ignores state->grip for TAPPING (screen-based) target
+    // ray mode, so we don't bother filling it in here. If this does get used at
+    // some point in the future, this should be set to the inverse of the
+    // pose rigid transform.
+
+    // Get a viewer-space ray from screen-space coordinates by applying the
+    // inverse of the projection matrix. Z coordinate of -1 means the point will
+    // be projected onto the projection matrix near plane. See also
+    // third_party/blink/renderer/modules/xr/xr_view.cc's UnprojectPointer.
+    const float x_normalized =
+        screen_last_touch.x() / transfer_size_.width() * 2.f - 1.f;
+    const float y_normalized =
+        (1.f - screen_last_touch.y() / transfer_size_.height()) * 2.f - 1.f;
+    gfx::Point3F touch_point(x_normalized, y_normalized, -1.f);
+    DVLOG(3) << __func__ << ": touch_point=" << touch_point.ToString();
+    inverse_projection_.TransformPoint(&touch_point);
+    DVLOG(3) << __func__ << ": unprojected=" << touch_point.ToString();
+
+    // Ray points along -Z in ray space, so we need to flip it to get
+    // the +Z axis unit vector.
+    gfx::Vector3dF ray_backwards(-touch_point.x(), -touch_point.y(),
+                                 -touch_point.z());
+    gfx::Vector3dF new_z;
+    bool can_normalize = ray_backwards.GetNormalized(&new_z);
+    DCHECK(can_normalize);
+
+    // Complete the ray-space basis by adding X and Y unit
+    // vectors based on cross products.
+    const gfx::Vector3dF kUp(0.f, 1.f, 0.f);
+    gfx::Vector3dF new_x(kUp);
+    new_x.Cross(new_z);
+    new_x.GetNormalized(&new_x);
+    gfx::Vector3dF new_y(new_z);
+    new_y.Cross(new_x);
+    new_y.GetNormalized(&new_y);
+
+    // Fill in the transform matrix in row-major order. The first three columns
+    // contain the basis vectors, the fourth column the position offset.
+    gfx::Transform viewer_from_pointer(
+        new_x.x(), new_y.x(), new_z.x(), touch_point.x(),  // row 1
+        new_x.y(), new_y.y(), new_z.y(), touch_point.y(),  // row 2
+        new_x.z(), new_y.z(), new_z.z(), touch_point.z(),  // row 3
+        0, 0, 0, 1);
+    DVLOG(3) << __func__ << ": viewer_from_pointer=\n"
+             << viewer_from_pointer.ToString();
+
+    state->description->input_from_pointer = viewer_from_pointer;
+
+    // Create the gamepad object and modify necessary fields.
+    state->gamepad = device::Gamepad{};
+    state->gamepad->connected = true;
+    state->gamepad->id[0] = '\0';
+    state->gamepad->timestamp =
+        base::TimeTicks::Now().since_origin().InMicroseconds();
+
+    state->gamepad->axes_length = 2;
+    state->gamepad->axes[0] = x_normalized;
+    state->gamepad->axes[1] =
+        -y_normalized;  //  Gamepad's Y axis is actually
+                        //  inverted (1.0 means "backward").
+
+    state->gamepad->buttons_length = 3;  // 2 placeholders + the real one
+    // Default-constructed buttons are already valid placeholders.
+    state->gamepad->buttons[2].touched = true;
+    state->gamepad->buttons[2].value = 1.0;
+    state->gamepad->mapping = device::GamepadMapping::kNone;
+    state->gamepad->hand = device::GamepadHand::kNone;
+
+    result.push_back(std::move(state));
+  }
+
+  // All the input source IDs that are no longer touching need to remain unused
+  // for at least one frame. For now, we always assign new ID for input source
+  // so there's no need to remember the IDs that have to be put on hold. Just
+  // clean up all the no longer touching pointers:
+  std::unordered_map<uint32_t, ScreenTouchEvent> still_touching_events;
+  for (const auto& screen_touch_event : screen_touch_events_) {
+    if (!screen_touch_event.second.screen_touch_active) {
+      // This pointer is no longer touching - remove it from the mapping, do not
+      // consider it as still touching:
+      pointer_id_to_input_source_id_.erase(
+          screen_touch_event.second.pointer_id);
+    } else {
+      still_touching_events.insert(screen_touch_event);
+    }
+  }
+
+  screen_touch_events_.swap(still_touching_events);
+
+  return result;
 }
 
 void ArCoreGl::Pause() {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.h b/chrome/browser/android/vr/arcore_device/arcore_gl.h
index d45d976..1365651 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.h
@@ -143,8 +143,14 @@
   void OnWebXrTokenSignaled(int16_t frame_index,
                             std::unique_ptr<gfx::GpuFence> gpu_fence);
 
-  void OnScreenTouch(bool touching, const gfx::PointF& touch_point);
-  mojom::XRInputSourceStatePtr GetInputSourceState();
+  // Notifies that the screen was touched at |touch_point| using a pointer.
+  // |touching| will be set to true if the screen is still touched. |is_primary|
+  // signifies that the used pointer is considered primary.
+  void OnScreenTouch(bool is_primary,
+                     bool touching,
+                     int32_t pointer_id,
+                     const gfx::PointF& touch_point);
+  std::vector<mojom::XRInputSourceStatePtr> GetInputSourceStates();
 
   base::WeakPtr<ArCoreGl> GetWeakPtr();
 
@@ -247,28 +253,45 @@
   // Currently estimated floor height.
   base::Optional<float> floor_height_estimate_;
 
-  std::vector<device::mojom::XRInputSourceStatePtr> input_states_;
-  gfx::PointF screen_last_touch_;
+  // Touch-related data.
+  // Android will report touch events via MotionEvent - see ArImmersiveOverlay
+  // for details.
+  struct ScreenTouchEvent {
+    gfx::PointF screen_last_touch;
 
-  // Screen touch start/end events get reported asynchronously. We want to
-  // report at least one "clicked" event even if start and end happen within a
-  // single frame. The "active" state corresponds to the current state and is
-  // updated asynchronously. The "pending" state is set to true whenever the
-  // screen is touched, but only gets cleared by the input source handler.
-  //
-  //    active   pending    event
-  //         0         0
-  //         1         1
-  //         1         1    pressed=true (selectstart)
-  //         1         1    pressed=true
-  //         0         1->0 pressed=false clicked=true (selectend, click)
-  //
-  //         0         0
-  //         1         1
-  //         0         1
-  //         0         1->0 pressed=false clicked=true (selectend, click)
-  float screen_touch_pending_ = false;
-  float screen_touch_active_ = false;
+    // Screen touch start/end events get reported asynchronously. We want to
+    // report at least one "clicked" event even if start and end happen within a
+    // single frame. The "active" state corresponds to the current state and is
+    // updated asynchronously. The "pending" state is set to true whenever the
+    // screen is touched, but only gets cleared by the input source handler.
+    //
+    //    active   pending    event
+    //         0         0
+    //         1         1
+    //         1         1    pressed=true (selectstart)
+    //         1         1    pressed=true
+    //         0         1->0 pressed=false clicked=true (selectend, click)
+    //
+    //         0         0
+    //         1         1
+    //         0         1
+    //         0         1->0 pressed=false clicked=true (selectend, click)
+    float screen_touch_pending = false;
+    float screen_touch_active = false;
+
+    // ID of the pointer that raised this event.
+    int32_t pointer_id;
+    bool is_primary;
+  };
+
+  // Map from input source ID to its latest information.
+  std::unordered_map<uint32_t, ScreenTouchEvent> screen_touch_events_;
+  // Map from pointer ID to input source ID currently assigned to that pointer.
+  std::unordered_map<int32_t, uint32_t> pointer_id_to_input_source_id_;
+
+  // TODO(https://crbug.com/1048329): change to a data type that will wrap
+  // around faster to exercise blink's handling of this case.
+  uint32_t next_input_source_id_ = 1;
 
   // Must be last.
   base::WeakPtrFactory<ArCoreGl> weak_ptr_factory_{this};
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 4541c9c..80d6e8a 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
@@ -78,11 +78,14 @@
 void ArCoreJavaUtils::OnDrawingSurfaceTouch(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj,
+    bool primary,
     bool touching,
+    int32_t pointer_id,
     float x,
     float y) {
-  DVLOG(3) << __func__ << ": touching=" << touching;
-  surface_touch_callback_.Run(touching, {x, y});
+  DVLOG(3) << __func__ << ": pointer_id=" << pointer_id
+           << " primary=" << primary << " touching=" << touching;
+  surface_touch_callback_.Run(primary, touching, pointer_id, {x, y});
 }
 
 void ArCoreJavaUtils::OnDrawingSurfaceDestroyed(
diff --git a/chrome/browser/android/vr/arcore_device/arcore_java_utils.h b/chrome/browser/android/vr/arcore_device/arcore_java_utils.h
index 327e54ca..bfc2fb4a 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_java_utils.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_java_utils.h
@@ -41,7 +41,9 @@
       int height);
   void OnDrawingSurfaceTouch(JNIEnv* env,
                              const base::android::JavaParamRef<jobject>& obj,
+                             bool primary,
                              bool touching,
+                             int32_t pointer_id,
                              float x,
                              float y);
   void OnDrawingSurfaceDestroyed(
@@ -49,7 +51,6 @@
       const base::android::JavaParamRef<jobject>& obj);
 
  private:
-
   base::android::ScopedJavaGlobalRef<jobject> j_arcore_java_utils_;
 
   SurfaceReadyCallback surface_ready_callback_;
diff --git a/chrome/browser/android/vr/arcore_device/arcore_session_utils.h b/chrome/browser/android/vr/arcore_device/arcore_session_utils.h
index 37d52d48..e48c9080 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_session_utils.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_session_utils.h
@@ -27,7 +27,10 @@
                                  display::Display::Rotation rotation,
                                  const gfx::Size& size)>;
 using SurfaceTouchCallback =
-    base::RepeatingCallback<void(bool touching, const gfx::PointF& location)>;
+    base::RepeatingCallback<void(bool is_primary,
+                                 bool touching,
+                                 int32_t pointer_id,
+                                 const gfx::PointF& location)>;
 using SurfaceDestroyedCallback = base::OnceClosure;
 
 class ArCoreSessionUtils {
diff --git a/chrome/browser/android/webapk/webapk.proto b/chrome/browser/android/webapk/webapk.proto
index 6d385945..0992e4a 100644
--- a/chrome/browser/android/webapk/webapk.proto
+++ b/chrome/browser/android/webapk/webapk.proto
@@ -103,6 +103,7 @@
   enum Usage {
     PRIMARY_ICON = 1;
     BADGE_ICON = 2;
+    SPLASH_ICON = 3;
   }
 
   // Image's URL.
diff --git a/chrome/browser/android/webapk/webapk_install_service.cc b/chrome/browser/android/webapk/webapk_install_service.cc
index 8a54ac57a..89f5ada 100644
--- a/chrome/browser/android/webapk/webapk_install_service.cc
+++ b/chrome/browser/android/webapk/webapk_install_service.cc
@@ -37,7 +37,6 @@
                                         const ShortcutInfo& shortcut_info,
                                         const SkBitmap& primary_icon,
                                         bool is_primary_icon_maskable,
-                                        const SkBitmap& badge_icon,
                                         WebappInstallSource install_source) {
   if (IsInstallInProgress(shortcut_info.manifest_url)) {
     ShortcutHelper::ShowWebApkInstallInProgressToast();
@@ -56,7 +55,6 @@
   auto observer = std::make_unique<LifetimeObserver>(web_contents);
   WebApkInstaller::InstallAsync(
       browser_context_, shortcut_info, primary_icon, is_primary_icon_maskable,
-      badge_icon,
       base::Bind(&WebApkInstallService::OnFinishedInstall,
                  weak_ptr_factory_.GetWeakPtr(), base::Passed(&observer),
                  shortcut_info, primary_icon, is_primary_icon_maskable));
diff --git a/chrome/browser/android/webapk/webapk_install_service.h b/chrome/browser/android/webapk/webapk_install_service.h
index 0120b28..fead0d7 100644
--- a/chrome/browser/android/webapk/webapk_install_service.h
+++ b/chrome/browser/android/webapk/webapk_install_service.h
@@ -71,7 +71,6 @@
                     const ShortcutInfo& shortcut_info,
                     const SkBitmap& primary_icon,
                     bool is_primary_icon_maskable,
-                    const SkBitmap& badge_icon,
                     WebappInstallSource install_source);
 
   // Talks to the Chrome WebAPK server to update a WebAPK on the server and to
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc
index da04415..22e0a30 100644
--- a/chrome/browser/android/webapk/webapk_installer.cc
+++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -181,11 +181,14 @@
 
 // Populates webapk::WebApk and returns it.
 // Must be called on a worker thread because it encodes an SkBitmap.
+// The splash icon can be passed either via |icon_url_to_murmur2_hash| or via
+// |splash_icon| parameter. |splash_icon| parameter is only used when the
+// splash icon URL is unknown.
 std::unique_ptr<std::string> BuildProtoInBackground(
     const ShortcutInfo& shortcut_info,
     const SkBitmap& primary_icon,
     bool is_primary_icon_maskable,
-    const SkBitmap& badge_icon,
+    const SkBitmap& splash_icon,
     const std::string& package_name,
     const std::string& version,
     std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash,
@@ -262,10 +265,11 @@
       best_primary_icon_image->add_purposes(webapk::Image::ANY);
     }
 
-    if (!badge_icon.drawsNothing()) {
-      webapk::Image* best_badge_icon_image = web_app_manifest->add_icons();
-      SetImageData(best_badge_icon_image, badge_icon);
-      best_badge_icon_image->add_usages(webapk::Image::BADGE_ICON);
+    if (!splash_icon.drawsNothing()) {
+      webapk::Image* splash_icon_image = web_app_manifest->add_icons();
+      SetImageData(splash_icon_image, splash_icon);
+      splash_icon_image->add_usages(webapk::Image::SPLASH_ICON);
+      splash_icon_image->add_purposes(webapk::Image::ANY);
     }
   }
 
@@ -285,12 +289,13 @@
         image->add_purposes(webapk::Image::ANY);
       }
     }
-    if (icon_url == shortcut_info.best_badge_icon_url.spec()) {
-      if (shortcut_info.best_badge_icon_url !=
+    if (icon_url == shortcut_info.splash_image_url.spec()) {
+      if (shortcut_info.splash_image_url !=
           shortcut_info.best_primary_icon_url) {
-        SetImageData(image, badge_icon);
+        image->set_image_data(it->second.data);
       }
-      image->add_usages(webapk::Image::BADGE_ICON);
+      image->add_usages(webapk::Image::SPLASH_ICON);
+      image->add_purposes(webapk::Image::ANY);
     }
   }
 
@@ -342,8 +347,10 @@
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
 
+  // TODO(crbug.com/1043271): Passing an empty SkBitmap for now as webapk update
+  // does not include splash_icon image yet.
   std::unique_ptr<std::string> proto = BuildProtoInBackground(
-      shortcut_info, primary_icon, is_primary_icon_maskable, badge_icon,
+      shortcut_info, primary_icon, is_primary_icon_maskable, SkBitmap(),
       package_name, version, std::move(icon_url_to_murmur2_hash),
       is_manifest_stale, update_reason);
 
@@ -385,12 +392,11 @@
                                    const ShortcutInfo& shortcut_info,
                                    const SkBitmap& primary_icon,
                                    bool is_primary_icon_maskable,
-                                   const SkBitmap& badge_icon,
                                    FinishCallback finish_callback) {
   // The installer will delete itself when it is done.
   WebApkInstaller* installer = new WebApkInstaller(context);
   installer->InstallAsync(shortcut_info, primary_icon, is_primary_icon_maskable,
-                          badge_icon, std::move(finish_callback));
+                          std::move(finish_callback));
 }
 
 // static
@@ -407,10 +413,9 @@
                                              const ShortcutInfo& shortcut_info,
                                              const SkBitmap& primary_icon,
                                              bool is_primary_icon_maskable,
-                                             const SkBitmap& badge_icon,
                                              FinishCallback callback) {
   installer->InstallAsync(shortcut_info, primary_icon, is_primary_icon_maskable,
-                          badge_icon, std::move(callback));
+                          std::move(callback));
 }
 
 // static
@@ -437,7 +442,7 @@
     const ShortcutInfo& shortcut_info,
     const SkBitmap& primary_icon,
     bool is_primary_icon_maskable,
-    const SkBitmap& badge_icon,
+    const SkBitmap& splash_icon,
     const std::string& package_name,
     const std::string& version,
     std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash,
@@ -446,7 +451,7 @@
   base::PostTaskAndReplyWithResult(
       GetBackgroundTaskRunner().get(), FROM_HERE,
       base::BindOnce(&BuildProtoInBackground, shortcut_info, primary_icon,
-                     is_primary_icon_maskable, badge_icon, package_name,
+                     is_primary_icon_maskable, splash_icon, package_name,
                      version, std::move(icon_url_to_murmur2_hash),
                      is_manifest_stale, WebApkUpdateReason::NONE),
       std::move(callback));
@@ -538,13 +543,11 @@
 void WebApkInstaller::InstallAsync(const ShortcutInfo& shortcut_info,
                                    const SkBitmap& primary_icon,
                                    bool is_primary_icon_maskable,
-                                   const SkBitmap& badge_icon,
                                    FinishCallback finish_callback) {
   install_duration_timer_.reset(new base::ElapsedTimer());
 
   install_shortcut_info_.reset(new ShortcutInfo(shortcut_info));
   install_primary_icon_ = primary_icon;
-  install_badge_icon_ = badge_icon;
   is_primary_icon_maskable_ = is_primary_icon_maskable;
   short_name_ = shortcut_info.short_name;
   finish_callback_ = std::move(finish_callback);
@@ -666,10 +669,10 @@
   // should be fast because the icon should be in the HTTP cache.
 
   std::set<GURL> icons{install_shortcut_info_->best_primary_icon_url};
-  if (!install_shortcut_info_->best_badge_icon_url.is_empty() &&
-      install_shortcut_info_->best_badge_icon_url !=
+  if (!install_shortcut_info_->splash_image_url.is_empty() &&
+      install_shortcut_info_->splash_image_url !=
           install_shortcut_info_->best_primary_icon_url) {
-    icons.insert(install_shortcut_info_->best_badge_icon_url);
+    icons.insert(install_shortcut_info_->splash_image_url);
   }
 
   for (const auto& shortcut_icon :
@@ -692,8 +695,10 @@
     return;
   }
 
+  // Using empty |splash_icon| here because in this code path (WebApk install),
+  // we are using the splash icon data from |hashes|.
   BuildProto(*install_shortcut_info_, install_primary_icon_,
-             is_primary_icon_maskable_, install_badge_icon_,
+             is_primary_icon_maskable_, SkBitmap() /* splash_icon */,
              "" /* package_name */, "" /* version */, std::move(*hashes),
              false /* is_manifest_stale */,
              base::BindOnce(&WebApkInstaller::SendRequest,
diff --git a/chrome/browser/android/webapk/webapk_installer.h b/chrome/browser/android/webapk/webapk_installer.h
index 1985baa5..447264b 100644
--- a/chrome/browser/android/webapk/webapk_installer.h
+++ b/chrome/browser/android/webapk/webapk_installer.h
@@ -63,7 +63,6 @@
                            const ShortcutInfo& shortcut_info,
                            const SkBitmap& primary_icon,
                            bool is_primary_icon_maskable,
-                           const SkBitmap& badge_icon,
                            FinishCallback finish_callback);
 
   // Creates a self-owned WebApkInstaller instance and talks to the Chrome
@@ -80,7 +79,6 @@
                                      const ShortcutInfo& shortcut_info,
                                      const SkBitmap& primary_icon,
                                      bool is_primary_icon_maskable,
-                                     const SkBitmap& badge_icon,
                                      FinishCallback callback);
 
   // Calls the private function |UpdateAsync| for testing.
@@ -111,7 +109,7 @@
       const ShortcutInfo& shortcut_info,
       const SkBitmap& primary_icon,
       bool is_primary_icon_maskable,
-      const SkBitmap& badge_icon,
+      const SkBitmap& splash_icon,
       const std::string& package_name,
       const std::string& version,
       std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash,
@@ -126,7 +124,7 @@
       const ShortcutInfo& shortcut_info,
       const SkBitmap& primary_icon,
       bool is_primary_icon_maskable,
-      const SkBitmap& badge_icon,
+      const SkBitmap& splash_icon,
       const std::string& package_name,
       const std::string& version,
       std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash,
@@ -164,7 +162,6 @@
   void InstallAsync(const ShortcutInfo& shortcut_info,
                     const SkBitmap& primary_icon,
                     bool is_primary_icon_maskable,
-                    const SkBitmap& badge_icon,
                     FinishCallback finish_callback);
 
   // Talks to the Chrome WebAPK server to update a WebAPK on the server and to
@@ -212,7 +209,6 @@
   // Data for installs.
   std::unique_ptr<ShortcutInfo> install_shortcut_info_;
   SkBitmap install_primary_icon_;
-  SkBitmap install_badge_icon_;
 
   bool is_primary_icon_maskable_;
 
diff --git a/chrome/browser/android/webapk/webapk_installer_unittest.cc b/chrome/browser/android/webapk/webapk_installer_unittest.cc
index 9f451a8..c4cf1bdf 100644
--- a/chrome/browser/android/webapk/webapk_installer_unittest.cc
+++ b/chrome/browser/android/webapk/webapk_installer_unittest.cc
@@ -48,7 +48,7 @@
 // data directory. Since WebApkInstaller does not try to decode the file as an
 // image it is OK that the file is not an image.
 const char* kBestPrimaryIconUrl = "/simple.html";
-const char* kBestBadgeIconUrl = "/nostore.html";
+const char* kBestSplashIconUrl = "/nostore.html";
 const char* kBestShortcutIconUrl = "/title1.html";
 
 // Icon which has Cross-Origin-Resource-Policy: same-origin set.
@@ -116,7 +116,7 @@
 
     // WebApkInstaller owns itself.
     WebApkInstaller::InstallAsyncForTesting(
-        installer.release(), info, SkBitmap(), false, SkBitmap(),
+        installer.release(), info, SkBitmap(), false,
         base::BindOnce(&WebApkInstallerRunner::OnCompleted,
                        base::Unretained(this)));
 
@@ -208,14 +208,14 @@
 
   void BuildSync(
       const GURL& best_primary_icon_url,
-      const GURL& best_badge_icon_url,
+      const GURL& splash_image_url,
       std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash,
       bool is_manifest_stale,
       const std::vector<GURL>& best_shortcut_icon_urls) {
     ShortcutInfo info(GURL::EmptyGURL());
     info.best_primary_icon_url = best_primary_icon_url;
-    info.best_badge_icon_url = best_badge_icon_url;
-    info.icon_urls = {best_primary_icon_url.spec(), best_badge_icon_url.spec(),
+    info.splash_image_url = splash_image_url;
+    info.icon_urls = {best_primary_icon_url.spec(), splash_image_url.spec(),
                       kUnusedIconPath};
 
     for (const GURL& shortcut_url : best_shortcut_icon_urls) {
@@ -226,9 +226,9 @@
     }
 
     SkBitmap primary_icon(gfx::test::CreateBitmap(144, 144));
-    SkBitmap badge_icon(gfx::test::CreateBitmap(72, 72));
+    SkBitmap splash_icon(gfx::test::CreateBitmap(72, 72));
     WebApkInstaller::BuildProto(
-        info, primary_icon, false /* is_primary_icon_maskable */, badge_icon,
+        info, primary_icon, false /* is_primary_icon_maskable */, splash_icon,
         "" /* package_name */, "" /* version */,
         std::move(icon_url_to_murmur2_hash), is_manifest_stale,
         base::BindOnce(&BuildProtoRunner::OnBuiltWebApkProto,
@@ -311,7 +311,7 @@
   ShortcutInfo DefaultShortcutInfo() {
     ShortcutInfo info(test_server_.GetURL(kStartUrl));
     info.best_primary_icon_url = test_server_.GetURL(kBestPrimaryIconUrl);
-    info.best_badge_icon_url = test_server_.GetURL(kBestBadgeIconUrl);
+    info.splash_image_url = test_server_.GetURL(kBestSplashIconUrl);
     info.best_shortcut_icon_urls.push_back(
         test_server_.GetURL(kBestShortcutIconUrl));
     return info;
@@ -404,12 +404,12 @@
   EXPECT_EQ(WebApkInstallResult::FAILURE, runner.result());
 }
 
-// Test that installation fails if fetching the bitmap at the best badge icon
+// Test that installation fails if fetching the bitmap at the best splash icon
 // URL returns no content. In a perfect world the fetch would always succeed
 // because the fetch for the same icon succeeded recently.
-TEST_F(WebApkInstallerTest, BestBadgeIconUrlDownloadTimesOut) {
+TEST_F(WebApkInstallerTest, BestSplashIconUrlDownloadTimesOut) {
   ShortcutInfo shortcut_info = DefaultShortcutInfo();
-  shortcut_info.best_badge_icon_url = test_server()->GetURL("/nocontent");
+  shortcut_info.splash_image_url = test_server()->GetURL("/nocontent");
 
   WebApkInstallerRunner runner;
   runner.RunInstallWebApk(CreateDefaultWebApkInstaller(), shortcut_info);
@@ -526,7 +526,7 @@
 }
 
 // When there is no Web Manifest available for a site, an empty
-// |best_primary_icon_url| and an empty |best_badge_icon_url| is used to build a
+// |best_primary_icon_url| and an empty |splash_image_url| is used to build a
 // WebApk update request. Tests the request can be built properly.
 TEST_F(WebApkInstallerTest, BuildWebApkProtoWhenManifestIsObsolete) {
   std::string icon_url_1 = test_server()->GetURL("/icon1.png").spec();
@@ -571,18 +571,18 @@
   std::string icon_url_1 = test_server()->GetURL("/icon.png").spec();
   std::string best_primary_icon_url =
       test_server()->GetURL(kBestPrimaryIconUrl).spec();
-  std::string best_badge_icon_url =
-      test_server()->GetURL(kBestBadgeIconUrl).spec();
+  std::string best_splash_icon_url =
+      test_server()->GetURL(kBestSplashIconUrl).spec();
   std::string best_shortcut_icon_url =
       test_server()->GetURL(kBestShortcutIconUrl).spec();
   std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash;
   icon_url_to_murmur2_hash[icon_url_1] = {"data0", "0"};
   icon_url_to_murmur2_hash[best_primary_icon_url] = {"data1", "1"};
-  icon_url_to_murmur2_hash[best_badge_icon_url] = {"data2", "2"};
+  icon_url_to_murmur2_hash[best_splash_icon_url] = {"data2", "2"};
   icon_url_to_murmur2_hash[best_shortcut_icon_url] = {"data3", "3"};
 
   std::unique_ptr<BuildProtoRunner> runner = CreateBuildProtoRunner();
-  runner->BuildSync(GURL(best_primary_icon_url), GURL(best_badge_icon_url),
+  runner->BuildSync(GURL(best_primary_icon_url), GURL(best_splash_icon_url),
                     icon_url_to_murmur2_hash, false /* is_manifest_stale*/,
                     {GURL(best_shortcut_icon_url)});
   webapk::WebApk* webapk_request = runner->GetWebApkRequest();
@@ -599,13 +599,14 @@
               testing::ElementsAre(webapk::Image::PRIMARY_ICON));
   EXPECT_TRUE(manifest.icons(0).has_image_data());
 
-  // Check protobuf fields for kBestBadgeIconUrl.
-  EXPECT_EQ(best_badge_icon_url, manifest.icons(1).src());
-  EXPECT_EQ(icon_url_to_murmur2_hash[best_badge_icon_url].hash,
+  // Check protobuf fields for kBestSplashIconUrl.
+  EXPECT_EQ(best_splash_icon_url, manifest.icons(1).src());
+  EXPECT_EQ(icon_url_to_murmur2_hash[best_splash_icon_url].hash,
             manifest.icons(1).hash());
   EXPECT_THAT(manifest.icons(1).usages(),
-              testing::ElementsAre(webapk::Image::BADGE_ICON));
-  EXPECT_TRUE(manifest.icons(1).has_image_data());
+              testing::ElementsAre(webapk::Image::SPLASH_ICON));
+  EXPECT_EQ(icon_url_to_murmur2_hash[best_splash_icon_url].data,
+            manifest.icons(1).image_data());
 
   // Check protobuf fields for unused icon.
   EXPECT_EQ(kUnusedIconPath, manifest.icons(2).src());
@@ -624,8 +625,8 @@
 
 // Tests a WebApk install or update request is built properly when the Chrome
 // knows the best icon URL of a site after fetching its Web Manifest, and
-// primary icon and badge icon share the same URL.
-TEST_F(WebApkInstallerTest, BuildWebApkProtoPrimaryIconAndBadgeIconSameUrl) {
+// primary icon and splash icon share the same URL.
+TEST_F(WebApkInstallerTest, BuildWebApkProtoPrimaryIconAndSplashIconSameUrl) {
   std::string icon_url_1 = test_server()->GetURL("/icon.png").spec();
   std::string best_icon_url = test_server()->GetURL(kBestPrimaryIconUrl).spec();
   std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash;
@@ -648,7 +649,7 @@
             manifest.icons(0).hash());
   EXPECT_THAT(manifest.icons(0).usages(),
               testing::ElementsAre(webapk::Image::PRIMARY_ICON,
-                                   webapk::Image::BADGE_ICON));
+                                   webapk::Image::SPLASH_ICON));
   EXPECT_TRUE(manifest.icons(0).has_image_data());
 
   EXPECT_EQ(best_icon_url, manifest.icons(1).src());
@@ -656,7 +657,7 @@
             manifest.icons(1).hash());
   EXPECT_THAT(manifest.icons(1).usages(),
               testing::ElementsAre(webapk::Image::PRIMARY_ICON,
-                                   webapk::Image::BADGE_ICON));
+                                   webapk::Image::SPLASH_ICON));
   EXPECT_TRUE(manifest.icons(1).has_image_data());
 
   // Check protobuf fields for unused icon.
@@ -741,3 +742,55 @@
   // This is a duplicate icon, so the data won't be included again.
   EXPECT_EQ(manifest.shortcuts(1).icons(0).image_data(), "");
 }
+
+TEST_F(WebApkInstallerTest, BuildWebApkProtoSplashIconAndShortcutIconSameUrl) {
+  std::string icon_url_1 = test_server()->GetURL("/icon.png").spec();
+  std::string best_icon_url = test_server()->GetURL(kBestPrimaryIconUrl).spec();
+  std::map<std::string, WebApkIconHasher::Icon> icon_url_to_murmur2_hash;
+  icon_url_to_murmur2_hash[icon_url_1] = {"data1", "1"};
+  icon_url_to_murmur2_hash[best_icon_url] = {"data0", "0"};
+
+  std::unique_ptr<BuildProtoRunner> runner = CreateBuildProtoRunner();
+  runner->BuildSync(GURL(icon_url_1), GURL(best_icon_url),
+                    icon_url_to_murmur2_hash, false /* is_manifest_stale*/,
+                    {GURL(best_icon_url)});
+  webapk::WebApk* webapk_request = runner->GetWebApkRequest();
+  ASSERT_NE(nullptr, webapk_request);
+
+  webapk::WebAppManifest manifest = webapk_request->manifest();
+  ASSERT_EQ(3, manifest.icons_size());
+  ASSERT_EQ(manifest.shortcuts_size(), 1);
+
+  // Check primary icon fields.
+  EXPECT_EQ(icon_url_1, manifest.icons(0).src());
+  EXPECT_EQ(icon_url_to_murmur2_hash[icon_url_1].hash,
+            manifest.icons(0).hash());
+  EXPECT_THAT(manifest.icons(0).usages(),
+              testing::ElementsAre(webapk::Image::PRIMARY_ICON));
+  EXPECT_TRUE(manifest.icons(0).has_image_data());
+
+  // Check splash icon fields
+  EXPECT_EQ(best_icon_url, manifest.icons(1).src());
+  EXPECT_EQ(icon_url_to_murmur2_hash[best_icon_url].hash,
+            manifest.icons(1).hash());
+  EXPECT_THAT(manifest.icons(1).usages(),
+              testing::ElementsAre(webapk::Image::SPLASH_ICON));
+  EXPECT_TRUE(manifest.icons(1).has_image_data());
+  EXPECT_EQ(manifest.icons(1).image_data(),
+            icon_url_to_murmur2_hash[best_icon_url].data);
+
+  // Check protobuf fields for unused icon.
+  EXPECT_EQ(kUnusedIconPath, manifest.icons(2).src());
+  EXPECT_FALSE(manifest.icons(2).has_hash());
+  EXPECT_FALSE(manifest.icons(2).has_image_data());
+
+  // Check shortcut fields.
+  ASSERT_EQ(manifest.shortcuts_size(), 1);
+  ASSERT_EQ(manifest.shortcuts(0).icons_size(), 1);
+  EXPECT_EQ(manifest.shortcuts(0).icons(0).src(), best_icon_url);
+  EXPECT_EQ(manifest.shortcuts(0).icons(0).hash(),
+            icon_url_to_murmur2_hash[best_icon_url].hash);
+  EXPECT_TRUE(manifest.shortcuts(0).icons(0).has_image_data());
+  EXPECT_EQ(manifest.shortcuts(0).icons(0).image_data(),
+            icon_url_to_murmur2_hash[best_icon_url].data);
+}
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
index 619b8e6..28261d5 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
@@ -53,7 +53,6 @@
   params.valid_primary_icon = true;
   params.prefer_maskable_icon =
       ShortcutHelper::DoesAndroidSupportMaskableIcons();
-  params.valid_badge_icon = true;
   params.wait_for_worker = true;
   return params;
 }
@@ -254,10 +253,6 @@
           data.manifest->icons, shortcut_info_.ideal_splash_image_size_in_px,
           shortcut_info_.minimum_splash_image_size_in_px,
           blink::Manifest::ImageResource::Purpose::ANY);
-  if (data.badge_icon) {
-    shortcut_info_.best_badge_icon_url = data.badge_icon_url;
-    badge_icon_ = *data.badge_icon;
-  }
 
   installable_manager_->GetData(
       ParamsToPerformInstallableCheck(),
@@ -378,5 +373,6 @@
     primary_icon_ = icon_for_view;
   if (is_icon_generated)
     shortcut_info_.best_primary_icon_url = GURL();
-  observer_->OnDataAvailable(shortcut_info_, icon_for_view, badge_icon_);
+
+  observer_->OnDataAvailable(shortcut_info_, icon_for_view);
 }
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
index 291f3d2..4af2cae6 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
@@ -39,8 +39,7 @@
     // Called when all the data needed to prompt the user to add to home screen
     // is available.
     virtual void OnDataAvailable(const ShortcutInfo& info,
-                                 const SkBitmap& primary_icon,
-                                 const SkBitmap& badge_icon) = 0;
+                                 const SkBitmap& primary_icon) = 0;
 
    protected:
     virtual ~Observer() {}
@@ -63,7 +62,6 @@
       const WebApplicationInfo& web_app_info);
 
   // Accessors, etc.
-  const SkBitmap& badge_icon() const { return badge_icon_; }
   const SkBitmap& primary_icon() const { return primary_icon_; }
   ShortcutInfo& shortcut_info() { return shortcut_info_; }
   bool has_maskable_primary_icon() const { return has_maskable_primary_icon_; }
@@ -101,7 +99,6 @@
 
   // The icons must only be set on the UI thread for thread safety.
   SkBitmap raw_primary_icon_;
-  SkBitmap badge_icon_;
   SkBitmap primary_icon_;
   ShortcutInfo shortcut_info_;
   bool has_maskable_primary_icon_;
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher_unittest.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher_unittest.cc
index 43969ce..55cc520 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher_unittest.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher_unittest.cc
@@ -74,8 +74,7 @@
   }
 
   void OnDataAvailable(const ShortcutInfo& info,
-                       const SkBitmap& primary_icon,
-                       const SkBitmap& badge_icon) override {
+                       const SkBitmap& primary_icon) override {
     // This should only be called once.
     EXPECT_FALSE(data_available_);
     EXPECT_TRUE(title_available_);
@@ -162,9 +161,8 @@
         {std::move(errors), GURL(kDefaultManifestUrl), &manifest_,
          params.valid_primary_icon ? primary_icon_url_ : GURL(),
          params.valid_primary_icon ? primary_icon_.get() : nullptr,
-         params.prefer_maskable_icon,
-         params.valid_badge_icon ? badge_icon_url_ : GURL(),
-         params.valid_badge_icon ? badge_icon_.get() : nullptr,
+         params.prefer_maskable_icon, GURL() /* splash_icon_url */,
+         nullptr /* splash_icon */,
          params.valid_manifest ? is_installable : false,
          params.has_worker ? is_installable : false});
   }
@@ -178,10 +176,6 @@
       primary_icon_url_ = manifest_.icons[0].src;
       primary_icon_.reset(
           new SkBitmap(gfx::test::CreateBitmap(kIconSizePx, kIconSizePx)));
-
-      badge_icon_url_ = manifest_.icons[0].src;
-      badge_icon_.reset(
-          new SkBitmap(gfx::test::CreateBitmap(kIconSizePx, kIconSizePx)));
     }
   }
 
@@ -196,9 +190,7 @@
  private:
   blink::Manifest manifest_;
   GURL primary_icon_url_;
-  GURL badge_icon_url_;
   std::unique_ptr<SkBitmap> primary_icon_;
-  std::unique_ptr<SkBitmap> badge_icon_;
 
   bool is_installable_ = true;
 
@@ -324,8 +316,7 @@
   CheckHistograms(histograms);
 
   EXPECT_TRUE(fetcher->shortcut_info().best_primary_icon_url.is_empty());
-  EXPECT_TRUE(fetcher->badge_icon().drawsNothing());
-  EXPECT_TRUE(fetcher->shortcut_info().best_badge_icon_url.is_empty());
+  EXPECT_TRUE(fetcher->shortcut_info().splash_image_url.is_empty());
 }
 
 // Check that the AddToHomescreenDataFetcher::Observer methods are called
@@ -467,9 +458,8 @@
   EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
             GURL(kDefaultIconUrl));
 
-  // No badge icon as InstallableManager does not fetch badge icon.
-  EXPECT_TRUE(fetcher->badge_icon().drawsNothing());
-  EXPECT_TRUE(fetcher->shortcut_info().best_badge_icon_url.is_empty());
+  // Check that splash icon url has been selected.
+  EXPECT_EQ(fetcher->shortcut_info().splash_image_url, GURL(kDefaultIconUrl));
   CheckHistograms(histograms);
 }
 
diff --git a/chrome/browser/android/webapps/add_to_homescreen_installer.cc b/chrome/browser/android/webapps/add_to_homescreen_installer.cc
index b4b8831..6d547f1 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_installer.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_installer.cc
@@ -66,8 +66,7 @@
     const AddToHomescreenParams& params) {
   WebApkInstallService::Get(web_contents->GetBrowserContext())
       ->InstallAsync(web_contents, *(params.shortcut_info), params.primary_icon,
-                     params.has_maskable_primary_icon, params.badge_icon,
-                     params.install_source);
+                     params.has_maskable_primary_icon, params.install_source);
 }
 
 // static
diff --git a/chrome/browser/android/webapps/add_to_homescreen_mediator.cc b/chrome/browser/android/webapps/add_to_homescreen_mediator.cc
index 4674b575..56228b4 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_mediator.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_mediator.cc
@@ -154,15 +154,13 @@
 }
 
 void AddToHomescreenMediator::OnDataAvailable(const ShortcutInfo& info,
-                                              const SkBitmap& display_icon,
-                                              const SkBitmap& badge_icon) {
+                                              const SkBitmap& display_icon) {
   params_ = std::make_unique<AddToHomescreenParams>();
   params_->app_type = info.source == ShortcutInfo::SOURCE_ADD_TO_HOMESCREEN_PWA
                           ? AddToHomescreenParams::AppType::WEBAPK
                           : AddToHomescreenParams::AppType::SHORTCUT;
   params_->shortcut_info = std::make_unique<ShortcutInfo>(info);
   params_->primary_icon = data_fetcher_->primary_icon();
-  params_->badge_icon = badge_icon;
   params_->has_maskable_primary_icon =
       data_fetcher_->has_maskable_primary_icon();
   params_->install_source = InstallableMetrics::GetInstallSource(
diff --git a/chrome/browser/android/webapps/add_to_homescreen_mediator.h b/chrome/browser/android/webapps/add_to_homescreen_mediator.h
index f4a672be3..49a8357 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_mediator.h
+++ b/chrome/browser/android/webapps/add_to_homescreen_mediator.h
@@ -76,8 +76,7 @@
                             bool is_webapk_compatible) override;
 
   void OnDataAvailable(const ShortcutInfo& info,
-                       const SkBitmap& display_icon,
-                       const SkBitmap& badge_icon) override;
+                       const SkBitmap& display_icon) override;
 
   void RecordEventForAppMenu(AddToHomescreenInstaller::Event event,
                              const AddToHomescreenParams& a2hs_params);
diff --git a/chrome/browser/android/webapps/add_to_homescreen_params.h b/chrome/browser/android/webapps/add_to_homescreen_params.h
index 86a4525e..fe379856 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_params.h
+++ b/chrome/browser/android/webapps/add_to_homescreen_params.h
@@ -25,7 +25,6 @@
 
   AppType app_type;
   SkBitmap primary_icon;
-  SkBitmap badge_icon;
   bool has_maskable_primary_icon = false;
   std::unique_ptr<ShortcutInfo> shortcut_info;
   WebappInstallSource install_source;
diff --git a/chrome/browser/banners/app_banner_manager_android.cc b/chrome/browser/banners/app_banner_manager_android.cc
index c7df9395..3cc8415 100644
--- a/chrome/browser/banners/app_banner_manager_android.cc
+++ b/chrome/browser/banners/app_banner_manager_android.cc
@@ -165,7 +165,6 @@
 AppBannerManagerAndroid::ParamsToPerformInstallableWebAppCheck() {
   InstallableParams params =
       AppBannerManager::ParamsToPerformInstallableWebAppCheck();
-  params.valid_badge_icon = true;
   params.prefer_maskable_icon =
       ShortcutHelper::DoesAndroidSupportMaskableIcons();
 
@@ -187,18 +186,6 @@
   AppBannerManager::PerformInstallableWebAppCheck();
 }
 
-void AppBannerManagerAndroid::OnDidPerformInstallableWebAppCheck(
-    const InstallableData& data) {
-  if (data.badge_icon && !data.badge_icon->drawsNothing()) {
-    DCHECK(!data.badge_icon_url.is_empty());
-
-    badge_icon_url_ = data.badge_icon_url;
-    badge_icon_ = *data.badge_icon;
-  }
-
-  AppBannerManager::OnDidPerformInstallableWebAppCheck(data);
-}
-
 void AppBannerManagerAndroid::ResetCurrentPageData() {
   AppBannerManager::ResetCurrentPageData();
   native_app_data_.Reset();
@@ -214,9 +201,8 @@
   if (native_app_data_.is_null()) {
     a2hs_params->app_type = AddToHomescreenParams::AppType::WEBAPK;
     a2hs_params->shortcut_info = ShortcutHelper::CreateShortcutInfo(
-        manifest_url_, manifest_, primary_icon_url_, badge_icon_url_);
+        manifest_url_, manifest_, primary_icon_url_);
     a2hs_params->install_source = install_source;
-    a2hs_params->badge_icon = badge_icon_;
     a2hs_params->has_maskable_primary_icon = has_maskable_primary_icon_;
   } else {
     a2hs_params->app_type = AddToHomescreenParams::AppType::NATIVE;
diff --git a/chrome/browser/banners/app_banner_manager_android.h b/chrome/browser/banners/app_banner_manager_android.h
index b11c3b7..3782f6b 100644
--- a/chrome/browser/banners/app_banner_manager_android.h
+++ b/chrome/browser/banners/app_banner_manager_android.h
@@ -84,8 +84,6 @@
   void PerformInstallableChecks() override;
   InstallableParams ParamsToPerformInstallableWebAppCheck() override;
   void PerformInstallableWebAppCheck() override;
-  void OnDidPerformInstallableWebAppCheck(
-      const InstallableData& result) override;
   void ResetCurrentPageData() override;
   void ShowBannerUi(WebappInstallSource install_source) override;
   void MaybeShowAmbientBadge() override;
@@ -133,12 +131,6 @@
   void RecordEventForAppBanner(AddToHomescreenInstaller::Event event,
                                const AddToHomescreenParams& a2hs_params);
 
-  // The URL of the badge icon.
-  GURL badge_icon_url_;
-
-  // The badge icon object.
-  SkBitmap badge_icon_;
-
   // The Java-side AppBannerManager.
   base::android::ScopedJavaGlobalRef<jobject> java_banner_manager_;
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index b5fd789..7dea8fb6 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -122,6 +122,7 @@
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "chrome/browser/safe_browsing/url_checker_delegate_impl.h"
+#include "chrome/browser/safe_browsing/url_lookup_service_factory.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/sharing/sms/sms_remote_fetcher.h"
 #include "chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h"
@@ -243,6 +244,7 @@
 #include "components/safe_browsing/core/db/database_manager.h"
 #include "components/safe_browsing/core/features.h"
 #include "components/safe_browsing/core/realtime/policy_engine.h"
+#include "components/safe_browsing/core/realtime/url_lookup_service.h"
 #include "components/safe_browsing/core/verdict_cache_manager.h"
 #include "components/security_interstitials/content/origin_policy_ui.h"
 #include "components/security_interstitials/content/ssl_cert_reporter.h"
@@ -4233,15 +4235,23 @@
             ? IdentityManagerFactory::GetForProfile(profile)
             : nullptr;
 
-    // TODO(crbug.com/1050859): Get url_lookup_service from
-    // url_lookup_service_factory and pass it into the throttle.
+    // |url_lookup_service| is used when real time url check is enabled.
+    safe_browsing::RealTimeUrlLookupService* url_lookup_service =
+        // |safe_browsing_service_| may be unavailable in tests.
+        safe_browsing_service_ &&
+                safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
+                    profile)
+            ? safe_browsing::RealTimeUrlLookupServiceFactory::GetForProfile(
+                  profile)
+            : nullptr;
 
     result.push_back(safe_browsing::BrowserURLLoaderThrottle::Create(
         base::BindOnce(
             &ChromeContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate,
             base::Unretained(this),
             profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)),
-        wc_getter, frame_tree_node_id, cache_manager, identity_manager));
+        wc_getter, frame_tree_node_id, cache_manager, identity_manager,
+        url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr));
   }
 #endif
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 4f5dfc4..73f7ef0 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -837,6 +837,8 @@
     "child_accounts/time_limits/app_time_policy_helpers.h",
     "child_accounts/time_limits/app_types.cc",
     "child_accounts/time_limits/app_types.h",
+    "child_accounts/time_limits/persisted_app_info.cc",
+    "child_accounts/time_limits/persisted_app_info.h",
     "child_accounts/time_limits/web_time_activity_provider.cc",
     "child_accounts/time_limits/web_time_activity_provider.h",
     "child_accounts/time_limits/web_time_limit_enforcer.cc",
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
index 1e07d49..f3f9459d 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
@@ -8,14 +8,22 @@
 #include "base/stl_util.h"
 #include "base/time/default_tick_clock.h"
 #include "base/timer/timer.h"
+#include "base/values.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limit_utils.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_notification_delegate.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/services/app_service/public/mojom/types.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
 
 namespace chromeos {
 namespace app_time {
@@ -85,6 +93,10 @@
   return registry_->GetTimeLeftForApp(app_id);
 }
 
+void AppActivityRegistry::TestApi::SaveAppActivity() {
+  registry_->SaveAppActivity();
+}
+
 AppActivityRegistry::AppDetails::AppDetails() = default;
 
 AppActivityRegistry::AppDetails::AppDetails(const AppActivity& activity)
@@ -128,14 +140,24 @@
   return false;
 }
 
+// static
+void AppActivityRegistry::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterListPref(prefs::kPerAppTimeLimitsAppActivities);
+}
+
 AppActivityRegistry::AppActivityRegistry(
     AppServiceWrapper* app_service_wrapper,
-    AppTimeNotificationDelegate* notification_delegate)
-    : app_service_wrapper_(app_service_wrapper),
+    AppTimeNotificationDelegate* notification_delegate,
+    Profile* profile)
+    : profile_(profile),
+      app_service_wrapper_(app_service_wrapper),
       notification_delegate_(notification_delegate) {
   DCHECK(app_service_wrapper_);
   DCHECK(notification_delegate_);
-  // TODO(agawronska): Read stored data.
+  DCHECK(profile_);
+
+  InitializeRegistryFromPref();
+
   app_service_wrapper_->AddObserver(this);
 }
 
@@ -472,6 +494,7 @@
 
 void AppActivityRegistry::Add(const AppId& app_id) {
   activity_registry_[app_id].activity = AppActivity(AppState::kAvailable);
+  newly_installed_apps_.push_back(app_id);
   for (auto& observer : app_state_observers_)
     observer.OnAppInstalled(app_id);
 }
@@ -736,5 +759,82 @@
   }
 }
 
+void AppActivityRegistry::InitializeRegistryFromPref() {
+  PrefService* pref_service = profile_->GetPrefs();
+  const base::Value* value =
+      pref_service->GetList(prefs::kPerAppTimeLimitsAppActivities);
+  DCHECK(value);
+
+  const std::vector<PersistedAppInfo> applications_info =
+      PersistedAppInfo::PersistedAppInfosFromList(
+          value,
+          /* include_app_activity_array */ false);
+
+  for (const auto& app_info : applications_info) {
+    DCHECK(!base::Contains(activity_registry_, app_info.app_id()));
+
+    // Don't restore uninstalled application's data.
+    if (app_info.app_state() == AppState::kUninstalled)
+      continue;
+
+    activity_registry_[app_info.app_id()].activity =
+        AppActivity(app_info.app_state(), app_info.active_running_time());
+  }
+}
+
+PersistedAppInfo AppActivityRegistry::GetPersistedAppInfoForApp(
+    const AppId& app_id,
+    base::Time timestamp) {
+  DCHECK(base::Contains(activity_registry_, app_id));
+
+  AppDetails& details = activity_registry_.at(app_id);
+
+  // Updates |AppActivity::active_times_| to include the current activity up to
+  // |timestamp|.
+  details.activity.CaptureOngoingActivity(timestamp);
+
+  return PersistedAppInfo(app_id, details.activity.app_state(),
+                          details.activity.RunningActiveTime(),
+                          details.activity.TakeActiveTimes());
+}
+
+void AppActivityRegistry::SaveAppActivity() {
+  {
+    ListPrefUpdate update(profile_->GetPrefs(),
+                          prefs::kPerAppTimeLimitsAppActivities);
+    base::ListValue* list_value = update.Get();
+
+    const base::Time now = base::Time::Now();
+
+    base::Value::ListView list_view = list_value->GetList();
+    for (base::Value& entry : list_view) {
+      base::Optional<AppId> app_id = policy::AppIdFromAppInfoDict(entry);
+      DCHECK(app_id.has_value());
+
+      if (!base::Contains(activity_registry_, app_id.value())) {
+        base::Optional<AppState> state =
+            PersistedAppInfo::GetAppStateFromDict(&entry);
+        DCHECK(state.has_value() && state.value() == AppState::kUninstalled);
+        continue;
+      }
+
+      const PersistedAppInfo info =
+          GetPersistedAppInfoForApp(app_id.value(), now);
+      info.UpdateAppActivityPreference(&entry);
+    }
+
+    for (const AppId& app_id : newly_installed_apps_) {
+      const PersistedAppInfo info = GetPersistedAppInfoForApp(app_id, now);
+      base::Value value(base::Value::Type::DICTIONARY);
+      info.UpdateAppActivityPreference(&value);
+      list_value->Append(std::move(value));
+    }
+    newly_installed_apps_.clear();
+  }
+
+  // Ensure that the app activity is persisted.
+  profile_->GetPrefs()->CommitPendingWrite();
+}
+
 }  // namespace app_time
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
index 55aa1701..8a4c871 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
@@ -28,11 +28,15 @@
 class OneShotTimer;
 }  // namespace base
 
+class PrefRegistrySimple;
+class Profile;
+
 namespace chromeos {
 namespace app_time {
 
 class AppTimeLimitsWhitelistPolicyWrapper;
 class AppTimeNotificationDelegate;
+class PersistedAppInfo;
 
 // Keeps track of app activity and time limits information.
 // Stores app activity between user session. Information about uninstalled apps
@@ -48,6 +52,7 @@
 
     const base::Optional<AppLimit>& GetAppLimit(const AppId& app_id) const;
     base::Optional<base::TimeDelta> GetTimeLeft(const AppId& app_id) const;
+    void SaveAppActivity();
 
    private:
     AppActivityRegistry* const registry_;
@@ -75,8 +80,11 @@
     virtual void OnAppInstalled(const AppId& app_id) = 0;
   };
 
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
   AppActivityRegistry(AppServiceWrapper* app_service_wrapper,
-                      AppTimeNotificationDelegate* notification_delegate);
+                      AppTimeNotificationDelegate* notification_delegate,
+                      Profile* profile);
   AppActivityRegistry(const AppActivityRegistry&) = delete;
   AppActivityRegistry& operator=(const AppActivityRegistry&) = delete;
   ~AppActivityRegistry() override;
@@ -204,6 +212,21 @@
 
   void WebTimeLimitReached(base::Time timestamp);
 
+  // Initializes |activity_registry_| from the stored values in user pref.
+  // Installed applications, their AppStates and their running active times will
+  // be restored.
+  void InitializeRegistryFromPref();
+
+  // Updates |AppActivity::active_times_| to include the current activity up to
+  // |timestamp| then creates the most up to date instance of PersistedAppInfo.
+  PersistedAppInfo GetPersistedAppInfoForApp(const AppId& app_id,
+                                             base::Time timestamp);
+
+  // Saves app activity into user preference.
+  void SaveAppActivity();
+
+  Profile* const profile_;
+
   // Owned by AppTimeController.
   AppServiceWrapper* const app_service_wrapper_;
 
@@ -214,6 +237,10 @@
   base::ObserverList<AppStateObserver> app_state_observers_;
 
   std::map<AppId, AppDetails> activity_registry_;
+
+  // Newly installed applications which have not yet been added to the user
+  // pref.
+  std::vector<AppId> newly_installed_apps_;
 };
 
 }  // namespace app_time
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry_unittest.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry_unittest.cc
index c16264ba..9b23888 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry_unittest.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry_unittest.cc
@@ -17,9 +17,12 @@
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_notification_delegate.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/services/app_service/public/mojom/types.mojom.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
+#include "components/prefs/pref_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/client/window_types.h"
@@ -68,26 +71,37 @@
   void SetAppLimit(const AppId& app_id,
                    const base::Optional<AppLimit>& app_limit);
 
-  AppActivityRegistry& registry() { return registry_; }
-  AppActivityRegistry::TestApi& registry_test() { return registry_test_; }
+  void ReInitializeRegistry();
+
+  AppActivityRegistry& registry() {
+    EXPECT_TRUE(!!registry_.get());
+    return *registry_;
+  }
+  AppActivityRegistry::TestApi& registry_test() {
+    EXPECT_TRUE(registry_test_.get());
+    return *registry_test_;
+  }
 
   base::test::TaskEnvironment& task_environment() { return task_environment_; }
   AppTimeNotificationDelegateMock& notification_delegate_mock() {
     return notification_delegate_mock_;
   }
+  Profile& profile() { return profile_; }
 
  private:
   TestingProfile profile_;
   AppTimeNotificationDelegateMock notification_delegate_mock_;
   AppServiceWrapper wrapper_{&profile_};
-  AppActivityRegistry registry_{&wrapper_, &notification_delegate_mock_};
-  AppActivityRegistry::TestApi registry_test_{&registry_};
+  std::unique_ptr<AppActivityRegistry> registry_;
+  std::unique_ptr<AppActivityRegistry::TestApi> registry_test_;
 
   std::map<AppId, std::vector<std::unique_ptr<aura::Window>>> windows_;
 };
 
 void AppActivityRegistryTest::SetUp() {
   ChromeViewsTestBase::SetUp();
+  ReInitializeRegistry();
+
   registry().OnAppInstalled(GetChromeAppId());
   registry().OnAppInstalled(kApp1);
   registry().OnAppInstalled(kApp2);
@@ -109,10 +123,18 @@
 void AppActivityRegistryTest::SetAppLimit(
     const AppId& app_id,
     const base::Optional<AppLimit>& app_limit) {
-  registry_.SetAppLimit(app_id, app_limit);
+  registry().SetAppLimit(app_id, app_limit);
   task_environment_.RunUntilIdle();
 }
 
+void AppActivityRegistryTest::ReInitializeRegistry() {
+  registry_ = std::make_unique<AppActivityRegistry>(
+      &wrapper_, &notification_delegate_mock_, &profile_);
+
+  registry_test_ =
+      std::make_unique<AppActivityRegistry::TestApi>(registry_.get());
+}
+
 TEST_F(AppActivityRegistryTest, RunningActiveTimeCheck) {
   auto* app1_window = CreateWindowForApp(kApp1);
 
@@ -577,5 +599,77 @@
   EXPECT_EQ(registry().GetAppState(kApp1), AppState::kAlwaysAvailable);
 }
 
+TEST_F(AppActivityRegistryTest, RestoredApplicationInformation) {
+  auto* app1_window = CreateWindowForApp(kApp1);
+  base::TimeDelta active_time = base::TimeDelta::FromMinutes(30);
+
+  const AppLimit limit(AppRestriction::kTimeLimit, active_time,
+                       base::Time::Now());
+  SetAppLimit(kApp1, limit);
+
+  base::Time app1_start_time_1 = base::Time::Now();
+  registry().OnAppActive(kApp1, app1_window, app1_start_time_1);
+  task_environment().FastForwardBy(active_time / 2);
+
+  // Save app activity.
+  registry_test().SaveAppActivity();
+
+  base::Time app1_inactive_time_1 = base::Time::Now();
+  registry().OnAppInactive(kApp1, app1_window, app1_inactive_time_1);
+
+  // App1 is inactive for 5 minutes.
+  task_environment().FastForwardBy(base::TimeDelta::FromMinutes(5));
+
+  base::Time app1_start_time_2 = base::Time::Now();
+  registry().OnAppActive(kApp1, app1_window, app1_start_time_2);
+  task_environment().FastForwardBy(active_time / 2);
+
+  // Time limit is reached. App becomes inactive.
+  EXPECT_FALSE(registry().IsAppActive(kApp1));
+  base::Time app1_inactive_time_2 = base::Time::Now();
+
+  // Save app activity.
+  registry_test().SaveAppActivity();
+
+  // Now let's recreate AppActivityRegistry. Its state should be restored.
+  ReInitializeRegistry();
+
+  EXPECT_TRUE(registry().IsAppInstalled(kApp1));
+  EXPECT_TRUE(registry().IsAppInstalled(kApp2));
+  EXPECT_TRUE(registry().IsAppTimeLimitReached(kApp1));
+  EXPECT_TRUE(registry().IsAppAvailable(kApp2));
+  EXPECT_EQ(registry().GetActiveTime(kApp1), active_time);
+
+  // Now let's test that the app activity are stored appropriately.
+  const base::Value* value =
+      profile().GetPrefs()->GetList(prefs::kPerAppTimeLimitsAppActivities);
+
+  const std::vector<PersistedAppInfo> app_infos =
+      PersistedAppInfo::PersistedAppInfosFromList(
+          value,
+          /* include_app_activity_array */ true);
+
+  // 3 applications. kApp1, kApp2 and Chrome browser.
+  EXPECT_TRUE(app_infos.size() == 3);
+  std::vector<AppActivity::ActiveTime> app1_times = {{
+      AppActivity::ActiveTime(app1_start_time_1, app1_inactive_time_1),
+      AppActivity::ActiveTime(app1_start_time_2, app1_inactive_time_2),
+  }};
+
+  for (const auto& app_info : app_infos) {
+    if (app_info.app_id() == kApp1) {
+      const std::vector<AppActivity::ActiveTime> active_time =
+          app_info.active_times();
+      EXPECT_EQ(app1_times.size(), active_time.size());
+      for (size_t i = 0; i < app1_times.size(); i++) {
+        EXPECT_EQ(app1_times[i], active_time[i]);
+      }
+
+    } else {
+      EXPECT_TRUE(app_info.active_times().size() == 0);
+    }
+  }
+}
+
 }  // namespace app_time
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
index 29245a1..c9f6f5d 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
@@ -224,7 +224,8 @@
       app_service_wrapper_(std::make_unique<AppServiceWrapper>(profile)),
       app_registry_(
           std::make_unique<AppActivityRegistry>(app_service_wrapper_.get(),
-                                                this)),
+                                                this,
+                                                profile)),
       web_time_activity_provider_(std::make_unique<WebTimeActivityProvider>(
           this,
           app_service_wrapper_.get())) {
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
index dbfaf0f..cabed72 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 
 namespace chromeos {
@@ -32,6 +34,25 @@
   NOTREACHED();
 }
 
+// static
+bool CanMerge(const AppActivity::ActiveTime& t1,
+              const AppActivity::ActiveTime& t2) {
+  if (t1.active_from() <= t2.active_from() &&
+      t1.active_to() >=
+          t2.active_from() -
+              AppActivity::ActiveTime::kActiveTimeMergePrecision) {
+    return true;
+  }
+
+  if (t2.active_from() <= t1.active_from() &&
+      t2.active_to() >=
+          t1.active_from() -
+              AppActivity::ActiveTime::kActiveTimeMergePrecision) {
+    return true;
+  }
+  return false;
+}
+
 }  // namespace
 
 AppId::AppId(apps::mojom::AppType app_type, const std::string& app_id)
@@ -90,6 +111,22 @@
 
 AppLimit::~AppLimit() = default;
 
+// static
+base::Optional<AppActivity::ActiveTime> AppActivity::ActiveTime::Merge(
+    const ActiveTime& t1,
+    const ActiveTime& t2) {
+  if (!CanMerge(t1, t2))
+    return base::nullopt;
+
+  base::Time active_from = std::min(t1.active_from(), t2.active_from());
+  base::Time active_to = std::max(t1.active_to(), t2.active_to());
+  return AppActivity::ActiveTime(active_from, active_to);
+}
+
+// static
+const base::TimeDelta AppActivity::ActiveTime::kActiveTimeMergePrecision =
+    base::TimeDelta::FromSeconds(1);
+
 AppActivity::ActiveTime::ActiveTime(base::Time start, base::Time end)
     : active_from_(start), active_to_(end) {
   DCHECK_GT(active_to_, active_from_);
@@ -135,6 +172,11 @@
     : app_state_(app_state),
       running_active_time_(base::TimeDelta::FromSeconds(0)),
       last_updated_time_ticks_(base::TimeTicks::Now()) {}
+AppActivity::AppActivity(AppState app_state,
+                         base::TimeDelta running_active_time)
+    : app_state_(app_state),
+      running_active_time_(running_active_time),
+      last_updated_time_ticks_(base::TimeTicks::Now()) {}
 AppActivity::AppActivity(const AppActivity&) = default;
 AppActivity& AppActivity::operator=(const AppActivity&) = default;
 AppActivity::AppActivity(AppActivity&&) = default;
@@ -142,20 +184,10 @@
 AppActivity::~AppActivity() = default;
 
 void AppActivity::SetAppState(AppState app_state) {
-  if (is_active_) {
-    // Log the active time before  updating app_state
-    base::TimeTicks now = base::TimeTicks::Now();
-    base::TimeDelta active_time = now - last_updated_time_ticks_;
-
-    base::Time end_time = base::Time::Now();
-    base::Time start_time = end_time - active_time;
-
-    active_times_.push_back(ActiveTime(start_time, end_time));
-    running_active_time_ += active_time;
-  }
-
   app_state_ = app_state;
-  last_updated_time_ticks_ = base::TimeTicks::Now();
+  CaptureOngoingActivity(base::Time::Now());
+  if (!is_active_)
+    last_updated_time_ticks_ = base::TimeTicks::Now();
 }
 
 void AppActivity::SetAppActive(base::Time timestamp) {
@@ -169,34 +201,13 @@
 void AppActivity::SetAppInactive(base::Time timestamp) {
   if (!is_active_)
     return;
-
-  base::TimeTicks now = base::TimeTicks::Now();
-  base::TimeDelta active_time = now - last_updated_time_ticks_;
-  base::Time start_time = timestamp - active_time;
+  CaptureOngoingActivity(timestamp);
   is_active_ = false;
-  // Timestamps can be equal if SetAppInactive() is called directly after
-  // SetAppState(). Happens in tests.
-  DCHECK_GE(timestamp, start_time);
-  if (timestamp > start_time)
-    active_times_.push_back(ActiveTime(start_time, timestamp));
-
-  running_active_time_ += active_time;
-  last_updated_time_ticks_ = now;
 }
 
 void AppActivity::ResetRunningActiveTime(base::Time timestamp) {
+  CaptureOngoingActivity(timestamp);
   running_active_time_ = base::TimeDelta::FromMinutes(0);
-
-  if (!is_active_)
-    return;
-
-  // Log the active time before the until the reset.
-  base::TimeTicks now = base::TimeTicks::Now();
-  base::TimeDelta active_time = now - last_updated_time_ticks_;
-  base::Time start_time = timestamp - active_time;
-
-  active_times_.push_back(ActiveTime(start_time, timestamp));
-  last_updated_time_ticks_ = now;
 }
 
 base::TimeDelta AppActivity::RunningActiveTime() const {
@@ -207,6 +218,32 @@
          (base::TimeTicks::Now() - last_updated_time_ticks_);
 }
 
+void AppActivity::CaptureOngoingActivity(base::Time timestamp) {
+  if (!is_active_)
+    return;
+
+  // Log the active time before the until the reset.
+  base::TimeTicks now = base::TimeTicks::Now();
+  base::TimeDelta active_time = now - last_updated_time_ticks_;
+
+  // Update |running_active_time_|.
+  running_active_time_ += active_time;
+
+  base::Time start_time = timestamp - active_time;
+
+  // Timestamps can be equal if SetAppInactive() is called directly after
+  // SetAppState(). Happens in tests.
+  DCHECK_GE(timestamp, start_time);
+  if (timestamp > start_time)
+    active_times_.push_back(ActiveTime(start_time, timestamp));
+
+  last_updated_time_ticks_ = now;
+}
+
+std::vector<AppActivity::ActiveTime> AppActivity::TakeActiveTimes() {
+  return std::move(active_times_);
+}
+
 void AppActivity::RemoveActiveTimeEarlierThan(base::Time timestamp) {
   for (auto active_time = active_times_.begin();
        active_time != active_times_.end();) {
@@ -225,5 +262,4 @@
 }
 
 }  // namespace app_time
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types.h b/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
index 33e6efd..61adf47 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TYPES_H_
 #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TYPES_H_
 
-#include <list>
 #include <string>
+#include <vector>
 
 #include "base/optional.h"
 #include "base/time/time.h"
@@ -25,19 +25,21 @@
   kTimeLimit,
 };
 
-// State of the app. Used for activity recording and status reporting.
+// State of the app. Used for activity recording and status reporting. The enum
+// values are persisted in user pref service. Existing values should never be
+// deleted or reordered. New states should be appended at the end.
 enum class AppState {
   // App is available for the user.
-  kAvailable,
+  kAvailable = 0,
   // App cannot be restricted. Used for important system apps.
-  kAlwaysAvailable,
+  kAlwaysAvailable = 1,
   // App is not available for the user because of being blocked.
-  kBlocked,
+  kBlocked = 2,
   // App is not available for the user because daily time limit was reached.
-  kLimitReached,
+  kLimitReached = 3,
   // App is uninstalled. Activity might still be preserved and reported for
   // recently uninstalled apps.
-  kUninstalled,
+  kUninstalled = 4,
 };
 
 // Type of notification to show the child user.
@@ -136,6 +138,15 @@
  public:
   class ActiveTime {
    public:
+    static const base::TimeDelta kActiveTimeMergePrecision;
+
+    // If |t1| and |t2| overlap or are within |kActiveTimeMergePrecision| of
+    // each other, this static method creates a new ActiveTime with the earlier
+    // of |t1|'s or |t2|'s |active_from| and the later of |t1|'s or |t2|'s
+    // |active_to_|.
+    static base::Optional<ActiveTime> Merge(const ActiveTime& t1,
+                                            const ActiveTime& t2);
+
     ActiveTime(base::Time start, base::Time end);
     ActiveTime(const ActiveTime& rhs);
     ActiveTime& operator=(const ActiveTime& rhs);
@@ -164,6 +175,7 @@
 
   // Creates AppActivity and sets current |app_state_|.
   explicit AppActivity(AppState app_state);
+  AppActivity(AppState app_state, base::TimeDelta running_active_time);
   AppActivity(const AppActivity&);
   AppActivity& operator=(const AppActivity&);
   AppActivity(AppActivity&&);
@@ -182,12 +194,22 @@
 
   base::TimeDelta RunningActiveTime() const;
 
-  // Removes active time data older than given |timestamp|.
+  // Updates |active_times_| to include the current activity. If the app is
+  // active, it saves the activitity until |timestamp|.
+  void CaptureOngoingActivity(base::Time timestamp);
+
+  // Caller takes ownership of |active_times_| i.e. |active_times_| is moved and
+  // thus becomes empty after this method is called. Called from
+  // AppActivityRegistry::SaveAppActivity when the app activity is going to be
+  // saved in user preference.
+  std::vector<ActiveTime> TakeActiveTimes();
+
+  // TODO(yilkal) remove the following method.
   void RemoveActiveTimeEarlierThan(base::Time timestamp);
 
   bool is_active() const { return is_active_; }
   AppState app_state() const { return app_state_; }
-  const std::list<ActiveTime>& active_times() const { return active_times_; }
+  const std::vector<ActiveTime>& active_times() const { return active_times_; }
   AppNotification last_notification() const { return last_notification_; }
 
   void set_last_notification(AppNotification notification) {
@@ -216,7 +238,7 @@
   base::TimeDelta running_active_time_;
 
   // The time app was active.
-  std::list<ActiveTime> active_times_;
+  std::vector<ActiveTime> active_times_;
 
   // Time tick for the last time the activity was updated.
   base::TimeTicks last_updated_time_ticks_;
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc
index 8a06c9d..e0a061f 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc
@@ -91,6 +91,45 @@
   EXPECT_FALSE(active_time.IsLaterThan(equal_end));
 }
 
+TEST_F(ActiveTimeTest, MergeActiveTimesTest) {
+  const base::TimeDelta delta =
+      AppActivity::ActiveTime::kActiveTimeMergePrecision / 2;
+
+  base::Time time1 = TimeFromString("11 Jan 2020 10:00:00 PST");
+  base::Time time2 = TimeFromString("11 Jan 2020 10:10:00 PST");
+  base::Time time3 = TimeFromString("11 Jan 2020 10:20:00 PST");
+
+  AppActivity::ActiveTime active_time_1(time1, time2);
+  AppActivity::ActiveTime active_time_2(time2 + delta, time3);
+  AppActivity::ActiveTime active_time_3(time2 + 3 * delta, time3);
+
+  base::Optional<AppActivity::ActiveTime> merged_time1 =
+      AppActivity::ActiveTime::Merge(active_time_1, active_time_2);
+  EXPECT_TRUE(merged_time1.has_value());
+  EXPECT_EQ(merged_time1->active_from(), time1);
+  EXPECT_EQ(merged_time1->active_to(), time3);
+
+  base::Optional<AppActivity::ActiveTime> merged_time2 =
+      AppActivity::ActiveTime::Merge(active_time_2, active_time_1);
+  EXPECT_TRUE(merged_time2.has_value());
+  EXPECT_EQ(merged_time2->active_from(), time1);
+  EXPECT_EQ(merged_time2->active_to(), time3);
+
+  base::Optional<AppActivity::ActiveTime> merged_time3 =
+      AppActivity::ActiveTime::Merge(active_time_1, active_time_3);
+  EXPECT_FALSE(merged_time3.has_value());
+
+  base::Optional<AppActivity::ActiveTime> merged_time4 =
+      AppActivity::ActiveTime::Merge(active_time_3, active_time_1);
+  EXPECT_FALSE(merged_time4.has_value());
+
+  base::Optional<AppActivity::ActiveTime> merged_time5 =
+      AppActivity::ActiveTime::Merge(active_time_2, active_time_3);
+  EXPECT_TRUE(merged_time5.has_value());
+  EXPECT_EQ(merged_time5->active_from(), time2 + delta);
+  EXPECT_EQ(merged_time5->active_to(), time3);
+}
+
 TEST_F(AppActivityTest, RemoveActiveTimes) {
   base::test::TaskEnvironment task_environment(
       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.cc b/chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.cc
new file mode 100644
index 0000000..b04b576a
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.cc
@@ -0,0 +1,260 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h"
+
+namespace chromeos {
+namespace app_time {
+
+namespace {
+
+// The following keys are stored in user pref. Modification will result in
+// errors when parsing old data.
+constexpr char kAppInfoKey[] = "app_info";
+constexpr char kAppStateKey[] = "app_state";
+constexpr char kRunningActiveTimeKey[] = "running_active_time";
+constexpr char kActiveTimesKey[] = "active_times";
+constexpr char kActiveFromKey[] = "active_from";
+constexpr char kActiveToKey[] = "active_to";
+
+base::Optional<AppActivity::ActiveTime> AppActivityFromDict(
+    const base::Value& value) {
+  if (!value.is_dict()) {
+    VLOG(1) << "Value is not a dictionary";
+    return base::nullopt;
+  }
+
+  const std::string* active_from = value.FindStringKey(kActiveFromKey);
+  if (!active_from) {
+    VLOG(1) << "Invalid |active_from| entry in dictionary";
+    return base::nullopt;
+  }
+
+  const std::string* active_to = value.FindStringKey(kActiveToKey);
+  if (!active_to) {
+    VLOG(1) << "Invalid |active_to| entry in dictionary.";
+    return base::nullopt;
+  }
+
+  int64_t active_from_microseconds;
+  int64_t active_to_microseconds;
+  if (!base::StringToInt64(*active_from, &active_from_microseconds) ||
+      !base::StringToInt64(*active_to, &active_to_microseconds)) {
+    return base::nullopt;
+  }
+
+  base::Time active_from_time = base::Time::FromDeltaSinceWindowsEpoch(
+      base::TimeDelta::FromMicroseconds(active_from_microseconds));
+  base::Time active_to_time = base::Time::FromDeltaSinceWindowsEpoch(
+      base::TimeDelta::FromMicroseconds(active_to_microseconds));
+
+  return AppActivity::ActiveTime(active_from_time, active_to_time);
+}
+
+base::Value AppActivityToDict(const AppActivity::ActiveTime& active_time) {
+  base::Value value(base::Value::Type::DICTIONARY);
+
+  auto serializeTime = [](base::Time time) -> std::string {
+    return base::NumberToString(
+        time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+  };
+
+  value.SetStringKey(kActiveFromKey, serializeTime(active_time.active_from()));
+  value.SetStringKey(kActiveToKey, serializeTime(active_time.active_to()));
+
+  return value;
+}
+
+std::vector<AppActivity::ActiveTime> AppActiveTimesFromList(
+    const base::Value* list) {
+  std::vector<AppActivity::ActiveTime> active_times;
+
+  if (!list || !list->is_list()) {
+    VLOG(1) << " Invalid app activity list";
+    return active_times;
+  }
+
+  base::Value::ConstListView list_view = list->GetList();
+
+  for (const auto& value : list_view) {
+    base::Optional<AppActivity::ActiveTime> entry = AppActivityFromDict(value);
+    if (!entry)
+      continue;
+    active_times.push_back(entry.value());
+  }
+
+  return active_times;
+}
+
+}  // namespace
+
+// static
+base::Optional<PersistedAppInfo> PersistedAppInfo::PersistedAppInfoFromDict(
+    const base::Value* dict,
+    bool include_app_activity_array) {
+  if (!dict || !dict->is_dict()) {
+    VLOG(1) << "Invalid application information.";
+    return base::nullopt;
+  }
+
+  base::Optional<AppId> app_id = policy::AppIdFromAppInfoDict(*dict);
+  if (!app_id)
+    return base::nullopt;
+
+  base::Optional<AppState> state = GetAppStateFromDict(dict);
+  if (!state) {
+    VLOG(1) << "Invalid application state.";
+    return base::nullopt;
+  }
+
+  const std::string* running_active_time =
+      dict->FindStringKey(kRunningActiveTimeKey);
+  if (!running_active_time) {
+    VLOG(1) << "Invalid running active time.";
+    return base::nullopt;
+  }
+
+  int64_t running_active_time_int;
+  if (!base::StringToInt64(*running_active_time, &running_active_time_int)) {
+    VLOG(1) << "Invalid running active time.";
+    return base::nullopt;
+  }
+
+  std::vector<AppActivity::ActiveTime> active_times;
+  if (include_app_activity_array) {
+    const base::Value* list = dict->FindListKey(kActiveTimesKey);
+    active_times = AppActiveTimesFromList(list);
+  }
+
+  return PersistedAppInfo(
+      app_id.value(), state.value(),
+      base::TimeDelta::FromMicroseconds(running_active_time_int),
+      std::move(active_times));
+}
+
+// static
+std::vector<PersistedAppInfo> PersistedAppInfo::PersistedAppInfosFromList(
+    const base::Value* value,
+    bool include_app_activity_array) {
+  std::vector<PersistedAppInfo> apps_info;
+  if (!value || !value->is_list())
+    return apps_info;
+
+  base::Value::ConstListView list_view = value->GetList();
+
+  for (const auto& per_app_info : list_view) {
+    base::Optional<PersistedAppInfo> info =
+        PersistedAppInfoFromDict(&per_app_info, include_app_activity_array);
+    if (!info.has_value())
+      continue;
+
+    apps_info.push_back(std::move(info.value()));
+  }
+
+  return apps_info;
+}
+
+// static
+base::Optional<AppState> PersistedAppInfo::GetAppStateFromDict(
+    const base::Value* value) {
+  if (!value || !value->is_dict())
+    return base::nullopt;
+
+  base::Optional<int> state = value->FindIntKey(kAppStateKey);
+  if (!state.has_value())
+    return base::nullopt;
+
+  return static_cast<AppState>(state.value());
+}
+
+PersistedAppInfo::PersistedAppInfo(
+    const AppId& app_id,
+    AppState state,
+    base::TimeDelta active_running_time,
+    std::vector<AppActivity::ActiveTime> active_times)
+    : app_id_(app_id),
+      app_state_(state),
+      active_running_time_(active_running_time),
+      active_times_(active_times) {}
+
+PersistedAppInfo::PersistedAppInfo(const PersistedAppInfo& info)
+    : app_id_(info.app_id_),
+      app_state_(info.app_state_),
+      active_running_time_(info.active_running_time_),
+      active_times_(info.active_times_) {}
+
+PersistedAppInfo::PersistedAppInfo(PersistedAppInfo&& info)
+    : app_id_(info.app_id_),
+      app_state_(info.app_state_),
+      active_running_time_(info.active_running_time_),
+      active_times_(std::move(info.active_times_)) {}
+
+PersistedAppInfo& PersistedAppInfo::operator=(const PersistedAppInfo& info) {
+  app_id_ = info.app_id_;
+  app_state_ = info.app_state_;
+  active_running_time_ = info.active_running_time_;
+  active_times_ = info.active_times_;
+  return *this;
+}
+
+PersistedAppInfo& PersistedAppInfo::operator=(PersistedAppInfo&& info) {
+  app_id_ = info.app_id_;
+  app_state_ = info.app_state_;
+  active_running_time_ = info.active_running_time_;
+  active_times_ = std::move(info.active_times_);
+  return *this;
+}
+
+PersistedAppInfo::~PersistedAppInfo() = default;
+
+void PersistedAppInfo::UpdateAppActivityPreference(base::Value* dict) const {
+  DCHECK(!!dict && dict->is_dict());
+
+  dict->SetKey(kAppInfoKey, policy::AppIdToDict(app_id_));
+  dict->SetIntKey(kAppStateKey, static_cast<int>(app_state()));
+  dict->SetStringKey(
+      kRunningActiveTimeKey,
+      base::NumberToString(active_running_time().InMicroseconds()));
+
+  base::Value* value = dict->FindListKey(kActiveTimesKey);
+  if (!value || !value->is_list()) {
+    value =
+        dict->SetPath(kActiveTimesKey, base::Value(base::Value::Type::LIST));
+  }
+
+  if (active_times_.size() == 0)
+    return;
+
+  // start index into |active_times_|
+  size_t start_index = 0;
+
+  // If the last entry in |value| can be merged with the first entry in
+  // |active_times_| merge them.
+  base::Value::ListView list_view = value->GetList();
+  if (list_view.size() > 0) {
+    base::Value& mergeable_entry = list_view[list_view.size() - 1];
+    base::Optional<AppActivity::ActiveTime> active_time =
+        AppActivityFromDict(mergeable_entry);
+    DCHECK(active_time.has_value());
+
+    base::Optional<AppActivity::ActiveTime> merged =
+        AppActivity::ActiveTime::Merge(active_time.value(), active_times_[0]);
+    if (merged.has_value()) {
+      mergeable_entry = AppActivityToDict(merged.value());
+      start_index = 1;
+    }
+  }
+
+  for (size_t i = start_index; i < active_times_.size(); i++) {
+    value->Append(AppActivityToDict(active_times_[i]));
+  }
+}
+
+}  // namespace app_time
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.h b/chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.h
new file mode 100644
index 0000000..f3b764b
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limits/persisted_app_info.h
@@ -0,0 +1,61 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_PERSISTED_APP_INFO_H_
+#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_PERSISTED_APP_INFO_H_
+
+#include <vector>
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
+
+namespace base {
+class Value;
+}  // namespace base
+
+namespace chromeos {
+namespace app_time {
+
+class PersistedAppInfo {
+ public:
+  static base::Optional<PersistedAppInfo> PersistedAppInfoFromDict(
+      const base::Value* value,
+      bool include_app_activity_array);
+  static std::vector<PersistedAppInfo> PersistedAppInfosFromList(
+      const base::Value* value,
+      bool include_app_activity_array);
+  static base::Optional<AppState> GetAppStateFromDict(const base::Value* value);
+
+  PersistedAppInfo(const AppId& app_id,
+                   AppState state,
+                   base::TimeDelta active_running_time,
+                   std::vector<AppActivity::ActiveTime> active_times);
+  PersistedAppInfo(const PersistedAppInfo& info);
+  PersistedAppInfo(PersistedAppInfo&& info);
+  PersistedAppInfo& operator=(const PersistedAppInfo& info);
+  PersistedAppInfo& operator=(PersistedAppInfo&& info);
+
+  ~PersistedAppInfo();
+
+  void UpdateAppActivityPreference(base::Value* dict) const;
+
+  const AppId& app_id() const { return app_id_; }
+  AppState app_state() const { return app_state_; }
+  base::TimeDelta active_running_time() const { return active_running_time_; }
+  const std::vector<AppActivity::ActiveTime>& active_times() const {
+    return active_times_;
+  }
+
+ private:
+  AppId app_id_;
+  AppState app_state_;
+  base::TimeDelta active_running_time_;
+  std::vector<AppActivity::ActiveTime> active_times_;
+};
+
+}  // namespace app_time
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_PERSISTED_APP_INFO_H_
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 1558f2f..9804f6d 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -48,6 +48,7 @@
 #include "components/metrics/metrics_pref_names.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/user_manager/user.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_context.h"
@@ -60,7 +61,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
-#include "services/identity/public/mojom/identity_service.mojom.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -456,12 +456,8 @@
     return profile_->GetURLLoaderFactory();
   }
 
-  void BindIdentityAccessor(
-      mojo::PendingReceiver<identity::mojom::IdentityAccessor> receiver)
-      override {
-    auto* service = profile_->GetIdentityService();
-    if (service)
-      service->BindIdentityAccessor(std::move(receiver));
+  signin::IdentityManager* GetIdentityManager() override {
+    return IdentityManagerFactory::GetForProfile(profile_);
   }
 
   const AccountId& GetAccountId() override {
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 68c2c34..75b182d 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -568,6 +568,20 @@
   return ash::AppListViewState::kClosed;
 }
 
+ash::OverviewAnimationState ToOverviewAnimationState(
+    api::autotest_private::OverviewStateType state) {
+  switch (state) {
+    case api::autotest_private::OverviewStateType::OVERVIEW_STATE_TYPE_SHOWN:
+      return ash::OverviewAnimationState::kEnterAnimationComplete;
+    case api::autotest_private::OverviewStateType::OVERVIEW_STATE_TYPE_HIDDEN:
+      return ash::OverviewAnimationState::kExitAnimationComplete;
+    case api::autotest_private::OverviewStateType::OVERVIEW_STATE_TYPE_NONE:
+      break;
+  }
+  NOTREACHED();
+  return ash::OverviewAnimationState::kExitAnimationComplete;
+}
+
 ui::KeyboardCode StringToKeyCode(const std::string& str) {
   constexpr struct Map {
     const char* str;
@@ -2907,6 +2921,36 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// AutotestPrivateWaitForOverviewStateFunction
+///////////////////////////////////////////////////////////////////////////////
+
+AutotestPrivateWaitForOverviewStateFunction::
+    AutotestPrivateWaitForOverviewStateFunction() = default;
+AutotestPrivateWaitForOverviewStateFunction::
+    ~AutotestPrivateWaitForOverviewStateFunction() = default;
+
+ExtensionFunction::ResponseAction
+AutotestPrivateWaitForOverviewStateFunction::Run() {
+  std::unique_ptr<api::autotest_private::WaitForOverviewState::Params> params(
+      api::autotest_private::WaitForOverviewState::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+  const ash::OverviewAnimationState overview_state =
+      ToOverviewAnimationState(params->overview_state);
+  ash::OverviewTestApi().WaitForOverviewState(
+      overview_state,
+      base::BindOnce(&AutotestPrivateWaitForOverviewStateFunction::Done, this));
+  return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void AutotestPrivateWaitForOverviewStateFunction::Done(bool success) {
+  if (!success) {
+    Respond(Error("Overview animation was canceled."));
+    return;
+  }
+  Respond(NoArguments());
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // AutotestPrivateSetOverviewModeStateFunction
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
index fdbc758..01d7aca 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -815,6 +815,22 @@
   ResponseAction Run() override;
 };
 
+// Waits until overview has finished animating to a certain state.
+class AutotestPrivateWaitForOverviewStateFunction : public ExtensionFunction {
+ public:
+  AutotestPrivateWaitForOverviewStateFunction();
+  DECLARE_EXTENSION_FUNCTION("autotestPrivate.waitForOverviewState",
+                             AUTOTESTPRIVATE_WAITFOROVERVIEWSTATE)
+
+ private:
+  ~AutotestPrivateWaitForOverviewStateFunction() override;
+  ResponseAction Run() override;
+
+  // Invoked when the animation has completed. |animation_succeeded| is whether
+  // overview is in the target state.
+  void Done(bool success);
+};
+
 // Returns the overview mode state.
 class AutotestPrivateSetOverviewModeStateFunction : public ExtensionFunction {
  public:
diff --git a/chrome/browser/chromeos/hats/hats_notification_controller.cc b/chrome/browser/chromeos/hats/hats_notification_controller.cc
index 95100c7..0c3c1f65 100644
--- a/chrome/browser/chromeos/hats/hats_notification_controller.cc
+++ b/chrome/browser/chromeos/hats/hats_notification_controller.cc
@@ -137,6 +137,12 @@
   if (profile->IsGuestSession())
     return false;
 
+  // Do not show survey if this is a child profile, for now. See crbug/1055022.
+  // TODO(crbug/1050807): remove this check after enabling HaTS for supervised
+  // users.
+  if (profile->IsChild())
+    return false;
+
   const bool is_enterprise_enrolled = g_browser_process->platform_part()
                                           ->browser_policy_connector_chromeos()
                                           ->IsEnterpriseManaged();
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc b/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc
index 8b894b1..042675b 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -281,9 +282,9 @@
       AccountId::FromUserEmail(user_id));
   base::FilePath profile_path =
       ProfileHelper::GetProfilePathByUserIdHash(user->username_hash());
-  PostTaskAndReplyWithResult(
+  base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&LoadPasswordData, profile_path),
       base::BindOnce(&OnPasswordDataLoaded, success_callback,
diff --git a/chrome/browser/chromeos/login/test/device_state_mixin.cc b/chrome/browser/chromeos/login/test/device_state_mixin.cc
index 19d2907..a29630a8 100644
--- a/chrome/browser/chromeos/login/test/device_state_mixin.cc
+++ b/chrome/browser/chromeos/login/test/device_state_mixin.cc
@@ -44,6 +44,8 @@
   install_attrs_["enterprise.domain"] = domain;
   install_attrs_["enterprise.realm"] = realm;
   install_attrs_["enterprise.device_id"] = device_id;
+  if (!mode.empty())
+    install_attrs_["enterprise.owned"] = "true";
 
   cryptohome::SerializedInstallAttributes install_attrs;
   install_attrs.set_version(1);
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos_unittest.cc
index 7488fff..0b1e964 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos_unittest.cc
@@ -121,6 +121,7 @@
   void ResetToNonEnterprise() {
     store_->RemoveObserver(&observer_);
     store_.reset();
+    chromeos::tpm_util::InstallAttributesSet("enterprise.owned", std::string());
     install_attributes_.reset(
         new chromeos::InstallAttributes(chromeos::FakeCryptohomeClient::Get()));
     store_.reset(new DeviceCloudPolicyStoreChromeOS(
diff --git a/chrome/browser/dom_distiller/tab_utils_browsertest.cc b/chrome/browser/dom_distiller/tab_utils_browsertest.cc
index 20a1c8e..91bd927 100644
--- a/chrome/browser/dom_distiller/tab_utils_browsertest.cc
+++ b/chrome/browser/dom_distiller/tab_utils_browsertest.cc
@@ -36,6 +36,11 @@
 
 const char* kSimpleArticlePath = "/dom_distiller/simple_article.html";
 const char* kOriginalArticleTitle = "Test Page Title";
+#if defined(OS_ANDROID)
+const char* kExpectedArticleTitle = "Test Page Title";
+#else
+const char* kExpectedArticleTitle = "Test Page Title - Reader Mode";
+#endif  // defined(OS_ANDROID)
 
 std::unique_ptr<content::WebContents> NewContentsWithSameParamsAs(
     content::WebContents* source_web_contents) {
@@ -160,7 +165,7 @@
   EXPECT_NE(initial_web_contents, after_web_contents);
   EXPECT_TRUE(
       after_web_contents->GetLastCommittedURL().SchemeIs(kDomDistillerScheme));
-  EXPECT_EQ(kOriginalArticleTitle, GetPageTitle(after_web_contents));
+  EXPECT_EQ(kExpectedArticleTitle, GetPageTitle(after_web_contents));
 }
 
 IN_PROC_BROWSER_TEST_F(DomDistillerTabUtilsBrowserTest,
@@ -188,7 +193,7 @@
   // Verify the destination WebContents is showing distilled content.
   EXPECT_TRUE(destination_web_contents->GetLastCommittedURL().SchemeIs(
       kDomDistillerScheme));
-  EXPECT_EQ(kOriginalArticleTitle, GetPageTitle(destination_web_contents));
+  EXPECT_EQ(kExpectedArticleTitle, GetPageTitle(destination_web_contents));
 
   content::WebContentsDestroyedWatcher destroyed_watcher(
       destination_web_contents);
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
index 4a17827..0e1126e 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -13,6 +13,7 @@
 
 #include "base/bind.h"
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/values.h"
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
@@ -356,13 +357,13 @@
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA) {
     // If we're being asked to remove plugin data, check whether it's actually
     // supported.
-    PostTask(FROM_HERE,
-             {base::ThreadPool(), base::MayBlock(),
-              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
-              base::TaskPriority::USER_VISIBLE},
-             base::BindOnce(
-                 &BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported,
-                 this, PluginPrefs::GetForProfile(GetProfile())));
+    base::ThreadPool::PostTask(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+         base::TaskPriority::USER_VISIBLE},
+        base::BindOnce(
+            &BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported,
+            this, PluginPrefs::GetForProfile(GetProfile())));
   } else {
     StartRemoving();
   }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 25fba19..cd76b31 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -291,13 +291,11 @@
   {
     "name": "autofill-no-local-save-on-unmask-success",
     "owners": [ "jsaul@google.com" ],
-    // Must wait for the Autofill Auth Project to be launched.
     "expiry_milestone": 84
   },
   {
     "name": "autofill-no-local-save-on-upload-success",
     "owners": [ "jsaul@google.com", "annelim@google.com" ],
-    // Must wait for the Autofill Auth Project to be launched.
     "expiry_milestone": 84
   },
   {
@@ -1034,13 +1032,13 @@
   },
   {
     "name": "enable-autofill-credit-card-ablation-experiment",
-    "owners": [ "dlkumar@google.com" ],
+    "owners": [ "jsaul@google.com" ],
     "expiry_milestone": 88
   },
   {
     "name": "enable-autofill-credit-card-authentication",
     "owners": [ "jsaul@google.com", "manasverma@google.com" ],
-    "expiry_milestone": 84
+    "expiry_milestone": 87
   },
   {
     "name": "enable-autofill-credit-card-upload",
@@ -1057,7 +1055,7 @@
   },
   {
     "name": "enable-autofill-credit-card-upload-editable-expiration-date",
-    "owners": [ "hozhng@google.com", "jsaul@google.com" ],
+    "owners": [ "jsaul@google.com" ],
     "expiry_milestone": 83
   },
   {
@@ -1066,16 +1064,6 @@
     "expiry_milestone": 84
   },
   {
-    "name": "enable-autofill-do-not-migrate-unsupported-local-cards",
-    "owners": [ "sujiezhu@google.com", "jsaul@google.com" ],
-    "expiry_milestone": 80
-  },
-  {
-    "name": "enable-autofill-local-card-migration-uses-strike-system-v2",
-    "owners": [ "annelim@google.com", "jsaul@google.com" , "jiahuiguo@google.com"],
-    "expiry_milestone": 84
-  },
-  {
     "name": "enable-autofill-manual-fallback",
     "owners": [ "fhorschig@chromium.org" ],
     "expiry_milestone": 83
@@ -1086,11 +1074,6 @@
     "expiry_milestone": 78
   },
   {
-    "name": "enable-autofill-save-card-show-no-thanks",
-    "owners": ["siashah", "jsaul@google.com"],
-    "expiry_milestone": 82
-  },
-  {
     "name": "enable-autofill-upi-vpa",
     "owners": ["cfroussios"],
     "expiry_milestone": 88
@@ -3743,7 +3726,7 @@
   },
   {
     "name": "wallet-service-use-sandbox",
-    "owners": [ "jsaul@google.com", "jiahuiguo", "payments-autofill-team@google.com" ],
+    "owners": [ "jsaul@google.com", "payments-autofill-team@google.com" ],
     // This flag is used by testing teams to run Google Payments calls against
     // the development server environment.
     "expiry_milestone": -1
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 3b720aff..2214f1d 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -97,9 +97,7 @@
     &kAllowNewIncognitoTabIntents,
     &kAllowRemoteContextForNotifications,
     &kAndroidBlockIntentNonSafelistedHeaders,
-    &kAndroidNightMode,
     &kAndroidNightModeCCT,
-    &kAndroidNightModeForQ,
     &kAndroidNightModeTabReparenting,
     &kAndroidPayIntegrationV1,
     &kAndroidPayIntegrationV2,
@@ -273,15 +271,9 @@
     "AndroidBlockIntentNonSafelistedHeaders",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kAndroidNightMode{"AndroidNightMode",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kAndroidNightModeCCT{"AndroidNightModeCCT",
                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kAndroidNightModeForQ{"AndroidNightModeForQ",
-                                          base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kAndroidNightModeTabReparenting{
     "AndroidNightModeTabReparenting", 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 fb59349..8931548 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -16,9 +16,7 @@
 extern const base::Feature kAllowNewIncognitoTabIntents;
 extern const base::Feature kAllowRemoteContextForNotifications;
 extern const base::Feature kAndroidBlockIntentNonSafelistedHeaders;
-extern const base::Feature kAndroidNightMode;
 extern const base::Feature kAndroidNightModeCCT;
-extern const base::Feature kAndroidNightModeForQ;
 extern const base::Feature kAndroidNightModeTabReparenting;
 extern const base::Feature kAndroidPayIntegrationV1;
 extern const base::Feature kAndroidPayIntegrationV2;
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 2419612..fccd3d1 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
@@ -208,9 +208,7 @@
     public static final String ADJUST_WEBAPK_INSTALLATION_SPACE = "AdjustWebApkInstallationSpace";
     public static final String ANDROID_BLOCK_INTENT_NON_SAFELISTED_HEADERS =
             "AndroidBlockIntentNonSafelistedHeaders";
-    public static final String ANDROID_NIGHT_MODE = "AndroidNightMode";
     public static final String ANDROID_NIGHT_MODE_CCT = "AndroidNightModeCCT";
-    public static final String ANDROID_NIGHT_MODE_FOR_Q = "AndroidNightModeForQ";
     public static final String ANDROID_NIGHT_MODE_TAB_REPARENTING =
             "AndroidNightModeTabReparenting";
     public static final String ANDROID_PAY_INTEGRATION_V1 = "AndroidPayIntegrationV1";
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index 15d4d42..8586b4f 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -333,11 +333,6 @@
     public static final String FLAGS_CACHED_NETWORK_SERVICE_WARM_UP_ENABLED =
             "network_service_warm_up_enabled";
     /**
-     * Whether or not night mode is available.
-     * Default value is false.
-     */
-    public static final String FLAGS_CACHED_NIGHT_MODE_AVAILABLE = "night_mode_available";
-    /**
      * Whether or not night mode is available for custom tabs.
      * Default value is false.
      */
@@ -738,6 +733,7 @@
                 "home_page_button_force_enabled",
                 "homepage_tile_enabled",
                 "inflate_toolbar_on_background_thread",
+                "night_mode_available",
                 "night_mode_default_to_light",
                 "ntp_button_enabled",
                 "ntp_button_variant",
@@ -834,7 +830,6 @@
                 FLAGS_CACHED_INTEREST_FEED_CONTENT_SUGGESTIONS,
                 FLAGS_CACHED_LABELED_BOTTOM_TOOLBAR_ENABLED,
                 FLAGS_CACHED_NETWORK_SERVICE_WARM_UP_ENABLED,
-                FLAGS_CACHED_NIGHT_MODE_AVAILABLE,
                 FLAGS_CACHED_NIGHT_MODE_CCT_AVAILABLE,
                 FLAGS_CACHED_PRIORITIZE_BOOTSTRAP_TASKS,
                 FLAGS_CACHED_SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index a884a563..e5ad4514 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -255,6 +255,7 @@
 #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h"
 #include "chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service.h"
 #include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
@@ -996,6 +997,7 @@
   certificate_manager::CertificatesHandler::RegisterProfilePrefs(registry);
   chromeos::AccountManager::RegisterPrefs(registry);
   chromeos::ApkWebAppService::RegisterProfilePrefs(registry);
+  chromeos::app_time::AppActivityRegistry::RegisterProfilePrefs(registry);
   chromeos::app_time::AppTimeController::RegisterProfilePrefs(registry);
   chromeos::assistant::prefs::RegisterProfilePrefs(registry);
   chromeos::bluetooth::DebugLogsManager::RegisterPrefs(registry);
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 6a7c713..8e86c8f 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -610,6 +610,11 @@
     return prerender_link_manager;
   }
 
+  // Synchronization note: The IPCs used to communicate DOM events back to the
+  // referring web page (see blink::mojom::PrerenderHandleClient) may race w/
+  // the IPCs used here to inject script. The WaitFor* variants should be used
+  // when an event was expected to happen or to happen soon.
+
   int GetPrerenderEventCount(int index, const std::string& type) const {
     int event_count;
     std::string expression = base::StringPrintf(
@@ -630,10 +635,6 @@
     return GetPrerenderEventCount(index, "webkitprerenderload");
   }
 
-  int GetPrerenderDomContentLoadedEventCountForLinkNumber(int index) const {
-    return GetPrerenderEventCount(index, "webkitprerenderdomcontentloaded");
-  }
-
   bool DidReceivePrerenderStopEventForLinkNumber(int index) const {
     return GetPrerenderEventCount(index, "webkitprerenderstop") > 0;
   }
@@ -653,6 +654,14 @@
     CHECK_EQ(0, dummy);
   }
 
+  void WaitForPrerenderStartEventForLinkNumber(int index) const {
+    WaitForPrerenderEventCount(index, "webkitprerenderstart", 1);
+  }
+
+  void WaitForPrerenderStopEventForLinkNumber(int index) const {
+    WaitForPrerenderEventCount(index, "webkitprerenderstart", 1);
+  }
+
   bool HadPrerenderEventErrors() const {
     bool had_prerender_event_errors;
     CHECK(content::ExecuteScriptAndExtractBool(
@@ -753,17 +762,6 @@
     return &clock_;
   }
 
-  void SetMidLoadClockAdvance(base::SimpleTestTickClock* clock,
-                              base::TimeDelta delta) {
-    mid_load_clock_ = clock;
-    mid_load_clock_tick_advance_ = delta;
-  }
-
-  void ClearMidLoadClock() {
-    mid_load_clock_tick_advance_ = base::TimeDelta();
-    mid_load_clock_ = nullptr;
-  }
-
   // Makes |url| never respond on the first load, and then with the contents of
   // |file| afterwards. When the first load has been scheduled, runs
   // |callback_io| on the IO thread.
@@ -813,9 +811,12 @@
         NavigateWithPrerenders(loader_url, expected_final_status_queue);
     prerenders[0]->WaitForLoads(expected_number_of_loads);
 
-    if (!mid_load_clock_tick_advance_.is_zero()) {
-      EXPECT_TRUE(mid_load_clock_);
-      mid_load_clock_->Advance(mid_load_clock_tick_advance_);
+    // Ensure that the referring page receives the right start and load events.
+    WaitForPrerenderStartEventForLinkNumber(0);
+    if (check_load_events_) {
+      EXPECT_EQ(expected_number_of_loads, prerenders[0]->number_of_loads());
+      WaitForPrerenderEventCount(0, "webkitprerenderload",
+                                 expected_number_of_loads);
     }
 
     FinalStatus expected_final_status = expected_final_status_queue.front();
@@ -823,7 +824,7 @@
       // The prerender will abort on its own. Assert it does so correctly.
       prerenders[0]->WaitForStop();
       EXPECT_FALSE(prerenders[0]->contents());
-      EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
+      WaitForPrerenderStopEventForLinkNumber(0);
     } else {
       // Otherwise, check that it prerendered correctly.
       TestPrerenderContents* prerender_contents = prerenders[0]->contents();
@@ -837,13 +838,7 @@
       }
     }
 
-    // Test that the referring page received the right start and load events.
-    EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
-    if (check_load_events_) {
-      EXPECT_EQ(expected_number_of_loads, prerenders[0]->number_of_loads());
-      EXPECT_EQ(expected_number_of_loads,
-                GetPrerenderLoadEventCountForLinkNumber(0));
-    }
+    // Test for proper event ordering.
     EXPECT_FALSE(HadPrerenderEventErrors());
 
     return prerenders;
@@ -913,8 +908,6 @@
   std::string loader_path_;
   std::string loader_query_;
   base::test::ScopedFeatureList feature_list_;
-  base::TimeDelta mid_load_clock_tick_advance_;
-  base::SimpleTestTickClock* mid_load_clock_;
   std::unique_ptr<content::URLLoaderInterceptor> interceptor_;
 };
 
@@ -971,7 +964,7 @@
   RemoveLinkElement(0);
   prerender->WaitForStop();
 
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   EXPECT_FALSE(HadPrerenderEventErrors());
   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
@@ -988,20 +981,21 @@
   set_loader_query("links_to_insert=2");
   std::unique_ptr<TestPrerender> prerender = PrerenderTestURL(
       "/prerender/prerender_page.html", FINAL_STATUS_CANCELLED, 1);
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
+  WaitForPrerenderStartEventForLinkNumber(1);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
 
   RemoveLinkElement(0);
   RemoveLinkElement(1);
   prerender->WaitForStop();
 
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
+  WaitForPrerenderStartEventForLinkNumber(1);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   EXPECT_FALSE(HadPrerenderEventErrors());
+
   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
   // calls did a thread/process hop to the renderer which insured pending
   // renderer events have arrived.
@@ -1020,8 +1014,7 @@
   // Add a second prerender for the same link. It reuses the prerender, so only
   // the start event fires here.
   AddPrerender(url, 1);
-  WaitForPrerenderEventCount(1, "webkitprerenderstart", 1);
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
+  WaitForPrerenderStartEventForLinkNumber(1);
   EXPECT_EQ(0, GetPrerenderLoadEventCountForLinkNumber(1));
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
 
@@ -1029,9 +1022,9 @@
   RemoveLinkElement(1);
   prerender->WaitForStop();
 
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
+  WaitForPrerenderStartEventForLinkNumber(1);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   EXPECT_FALSE(HadPrerenderEventErrors());
   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
@@ -1046,15 +1039,15 @@
   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   set_loader_query("links_to_insert=2");
   PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
+  WaitForPrerenderStartEventForLinkNumber(1);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
 
   RemoveLinkElement(0);
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
+  WaitForPrerenderStartEventForLinkNumber(1);
   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   EXPECT_FALSE(HadPrerenderEventErrors());
   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
@@ -1528,10 +1521,8 @@
   PrerenderTestURL(replacement_path, FINAL_STATUS_SAFE_BROWSING, 0);
 }
 
-// Flaky on multiple platforms, http://crbug.com/1050143
 // Ensures that we do not prerender pages which have a malware iframe.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       DISABLED_PrerenderSafeBrowsingIframe) {
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingIframe) {
   GURL iframe_url = embedded_test_server()->GetURL(
       "/prerender/prerender_embedded_content.html");
   GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
@@ -1608,8 +1599,8 @@
   GetPrerenderManager()->CancelAllPrerenders();
   prerender->WaitForStop();
 
-  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
-  EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
+  WaitForPrerenderStartEventForLinkNumber(0);
+  WaitForPrerenderStopEventForLinkNumber(0);
   EXPECT_FALSE(HadPrerenderEventErrors());
 }
 
@@ -1756,10 +1747,8 @@
 }
 
 // Checks that non-http/https main page redirects cancel the prerender.
-// Disabled for flakes: crbug.com/1050143.
-IN_PROC_BROWSER_TEST_F(
-    PrerenderBrowserTest,
-    DISABLED_PrerenderCancelMainFrameRedirectUnsupportedScheme) {
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
+                       PrerenderCancelMainFrameRedirectUnsupportedScheme) {
   // Disable load event checks because they race with cancellation.
   DisableLoadEventCheck();
   GURL url = embedded_test_server()->GetURL(
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
index a40335f3..97abef4 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
@@ -73,6 +73,7 @@
     "metrics.js",
     "navigation_manager.js",
     "nodes/back_button_node.js",
+    "nodes/desktop_node.js",
     "nodes/editable_text_node.js",
     "nodes/group_node.js",
     "nodes/keyboard_node.js",
@@ -114,6 +115,7 @@
   sources = [
     "auto_scan_manager_test.js",
     "navigation_manager_test.js",
+    "nodes/desktop_node_test.js",
     "nodes/node_wrapper_test.js",
     "nodes/tab_node_test.js",
     "switch_access_predicate_test.js",
@@ -179,6 +181,7 @@
     ":back_button_node",
     ":background",
     ":commands",
+    ":desktop_node",
     ":editable_text_node",
     ":event_helper",
     ":focus_ring_manager",
@@ -231,6 +234,12 @@
   externs_list = [ "$externs_path/accessibility_private.js" ]
 }
 
+js_library("desktop_node") {
+  sources = [ "nodes/desktop_node.js" ]
+  deps = [ ":node_wrapper" ]
+  externs_list = [ "$externs_path/automation.js" ]
+}
+
 js_library("editable_text_node") {
   sources = [ "nodes/editable_text_node.js" ]
   deps = [
@@ -330,6 +339,7 @@
 
 js_library("navigation_manager") {
   deps = [
+    ":desktop_node",
     ":focus_ring_manager",
     ":keyboard_node",
     ":menu_manager",
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/commands.js b/chrome/browser/resources/chromeos/accessibility/switch_access/commands.js
index d6f4649..09ec2d7 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/commands.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/commands.js
@@ -8,14 +8,6 @@
  * Runs user commands.
  */
 class Commands {
-  // ============= Static Methods ===============
-
-  static initialize() {
-    Commands.instance = new Commands();
-  }
-
-  // ============= Private Methods ===============
-
   /** @private */
   constructor() {
     /**
@@ -32,6 +24,10 @@
         this.runCommand_.bind(this));
   }
 
+  static initialize() {
+    Commands.instance = new Commands();
+  }
+
   /**
    * Run the function binding for the specified command.
    * @param {!SwitchAccessCommand} command
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/event_helper.js b/chrome/browser/resources/chromeos/accessibility/switch_access/event_helper.js
index 3e7ea1c6..67acf74 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/event_helper.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/event_helper.js
@@ -25,7 +25,7 @@
    * Sends a synthetic mouse event.
    * @param {number} x
    * @param {number} y
-   * @param {number=} delayMs The delay between mouse press and mouse release,
+   * @param {?number} delayMs The delay between mouse press and mouse release,
    *     in milliseconds.
    */
   simulateMouseClick: (x, y, delayMs) => {
@@ -37,7 +37,7 @@
       chrome.accessibilityPrivate.sendSyntheticMouseEvent({type, x, y});
     };
 
-    if (delayMs) {
+    if (delayMs !== null) {
       setTimeout(callback, delayMs);
     } else {
       callback();
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/manifest.json.jinja2 b/chrome/browser/resources/chromeos/accessibility/switch_access/manifest.json.jinja2
index 7b4e35c..9c6a3fa 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/manifest.json.jinja2
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/manifest.json.jinja2
@@ -23,6 +23,7 @@
       "nodes/switch_access_node.js",
       "nodes/node_wrapper.js",
       "nodes/back_button_node.js",
+      "nodes/desktop_node.js",
       "nodes/editable_text_node.js",
       "nodes/group_node.js",
       "nodes/keyboard_node.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js
index 13acc57b..cb44247 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js
@@ -571,11 +571,6 @@
       this.exit();
       return;
     }
-    if (action === SAConstants.MenuAction.OPEN_KEYBOARD) {
-      this.navigationManager_.enterKeyboard();
-      this.exit();
-      return;
-    }
 
     // Handle global actions.
     if (action === SAConstants.MenuAction.SETTINGS) {
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
index bd2cc42..2ccdeed 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
@@ -16,7 +16,7 @@
     this.desktop_ = desktop;
 
     /** @private {!SARootNode} */
-    this.group_ = RootNodeWrapper.buildDesktopTree(this.desktop_);
+    this.group_ = DesktopNode.build(this.desktop_);
 
     /** @private {!SAChildNode} */
     this.node_ = this.group_.firstChild;
@@ -25,7 +25,7 @@
     this.groupStack_ = [];
 
     /** @private {!MenuManager} */
-    this.menuManager_ = new MenuManager(this, desktop);
+    this.menuManager_ = new MenuManager(this, this.desktop_);
 
     /** @private {!FocusRingManager} */
     this.focusRingManager_ = new FocusRingManager();
@@ -42,6 +42,18 @@
   // =============== Static Methods ==============
 
   /**
+   * Puts focus on the virtual keyboard, if the current node is a text input.
+   * TODO(crbug/946190): Handle the case where the user has not enabled the
+   *     onscreen keyboard.
+   */
+  static enterKeyboard() {
+    const navigator = NavigationManager.instance;
+    const keyboard = KeyboardRootNode.buildTree();
+    navigator.jumpTo_(keyboard);
+    navigator.node_.automationNode.focus();
+  }
+
+  /**
    * Open the Switch Access menu for the currently highlighted node. If there
    * are not enough actions available to trigger the menu, the current element
    * is selected.
@@ -56,6 +68,28 @@
     }
   }
 
+  static exitKeyboard() {
+    const navigator = NavigationManager.instance;
+    let foundKeyboard = navigator.group_ instanceof KeyboardRootNode;
+    for (const group of navigator.groupStack_) {
+      foundKeyboard |= group instanceof KeyboardRootNode;
+    }
+    // If we are not in the keyboard, do nothing.
+    if (!foundKeyboard) {
+      return;
+    }
+
+    while (navigator.groupStack_.length > 0) {
+      if (navigator.group_ instanceof KeyboardRootNode) {
+        break;
+      }
+      navigator.exitGroup_();
+    }
+    navigator.exitGroup_();
+
+    NavigationManager.moveToValidNode();
+  }
+
   /**
    * Forces the current node to be |node|.
    * Should only be called by subclasses of SARootNode and
@@ -79,8 +113,7 @@
       return NavigationManager.instance.group_;
     }
 
-    const desktopRoot =
-        RootNodeWrapper.buildDesktopTree(NavigationManager.instance.desktop_);
+    const desktopRoot = DesktopNode.build(NavigationManager.instance.desktop_);
     console.log(desktopRoot.debugString(
         wholeTree, '', NavigationManager.instance.node_));
     return desktopRoot;
@@ -164,7 +197,7 @@
     }
 
     // If there is no valid node in the group stack, go to the desktop.
-    navigator.setGroup_(RootNodeWrapper.buildDesktopTree(navigator.desktop_));
+    navigator.setGroup_(DesktopNode.build(navigator.desktop_));
     navigator.groupStack_ = [];
   }
 
@@ -181,6 +214,14 @@
   // =============== Instance Methods ==============
 
   /**
+   * Returns the desktop automation node object.
+   * @return {!chrome.automation.AutomationNode}
+   */
+  get desktopNode() {
+    return this.desktop_;
+  }
+
+  /**
    * Enters |this.node_|.
    */
   enterGroup() {
@@ -198,17 +239,6 @@
   }
 
   /**
-   * Puts focus on the virtual keyboard, if the current node is a text input.
-   * TODO(cbug/946190): Handle the case where the user has not enabled the
-   *     onscreen keyboard.
-   */
-  enterKeyboard() {
-    const keyboard = KeyboardRootNode.buildTree(this.desktop_);
-    this.node_.performAction(SAConstants.MenuAction.OPEN_KEYBOARD);
-    this.jumpTo_(keyboard);
-  }
-
-  /**
    * Selects the current node.
    */
   selectCurrentNode() {
@@ -227,7 +257,6 @@
       SwitchAccessMetrics.recordMenuAction(
           SAConstants.MenuAction.OPEN_KEYBOARD);
       this.node_.performAction(SAConstants.MenuAction.OPEN_KEYBOARD);
-      this.enterKeyboard();
       return;
     }
 
@@ -303,7 +332,7 @@
     }
 
     this.groupStack_ = [];
-    let group = RootNodeWrapper.buildDesktopTree(this.desktop_);
+    let group = DesktopNode.build(this.desktop_);
     while (ancestorList.length > 0) {
       const ancestor = ancestorList.pop();
       if (ancestor.role === chrome.automation.RoleType.DESKTOP) {
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 f8589f0e..f473e89 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
@@ -43,7 +43,7 @@
 function moveToPageContents() {
   const navigator = NavigationManager.instance;
   // Start from the desktop node.
-  navigator.group_ = RootNodeWrapper.buildDesktopTree(navigator.desktop_);
+  navigator.group_ = DesktopNode.build(navigator.desktop_);
   navigator.node_ = navigator.group_.firstChild;
 
   // The first item should be the browser window.
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js
index cdb07d8..1d8599e 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js
@@ -105,21 +105,18 @@
   }
 
   // ================= Static methods =================
-  /**
-   * Looks for the back button node.
-   * @param {!chrome.automation.AutomationNode} desktop The Switch Access panel
-   *     node.
-   */
-  static findAutomationNode(desktop) {
+
+  /** Looks for the back button node. */
+  static findAutomationNode() {
     const treeWalker = new AutomationTreeWalker(
-        desktop, constants.Dir.FORWARD,
+        NavigationManager.instance.desktopNode, constants.Dir.FORWARD,
         {visit: (node) => node.htmlAttributes.id === SAConstants.BACK_ID});
     BackButtonNode.automationNode_ = treeWalker.next().node;
 
     // TODO(anastasi): Generate event when Switch Access Panel is loaded instead
     // of polling.
     if (!BackButtonNode.automationNode_) {
-      setTimeout(() => BackButtonNode.findAutomationNode(desktop), 100);
+      setTimeout(BackButtonNode.findAutomationNode, 100);
     }
   }
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js
new file mode 100644
index 0000000..b69793da
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js
@@ -0,0 +1,87 @@
+// 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.
+
+/**
+ * This class handles interactions with the desktop automation node.
+ */
+class DesktopNode extends RootNodeWrapper {
+  /**
+   * @param {!AutomationNode} autoNode The automation node representing the
+   *     desktop.
+   */
+  constructor(autoNode) {
+    super(autoNode);
+  }
+
+  // ================= General methods =================
+
+  /** @override */
+  equals(other) {
+    // The underlying automation tree only has one desktop node, so all
+    // DesktopNode instances are equal.
+    return other instanceof DesktopNode;
+  }
+
+  /** @override */
+  isValidGroup() {
+    return true;
+  }
+
+  // ================= Private methods =================
+
+  /** @override */
+  refresh_() {
+    // Find the currently focused child.
+    let focusedChild = null;
+    for (const child of this.children) {
+      if (child.isFocused()) {
+        focusedChild = child;
+        break;
+      }
+    }
+
+    // Update this DesktopNode's children.
+    const childConstructor = (node) => NodeWrapper.create(node, this);
+    DesktopNode.findAndSetChildren(this, childConstructor);
+
+    // Set the new instance of that child to be the focused node.
+    for (const child of this.children) {
+      if (child.isEquivalentTo(focusedChild)) {
+        NavigationManager.forceFocusedNode(child);
+        return;
+      }
+    }
+
+    // If the previously focused node no longer exists, focus the first node in
+    // the group.
+    NavigationManager.forceFocusedNode(this.children[0]);
+  }
+
+  // ================= Static methods =================
+
+  /**
+   * @param {!AutomationNode} desktop
+   * @return {!DesktopNode}
+   */
+  static build(desktop) {
+    const root = new DesktopNode(desktop);
+    const childConstructor = (autoNode) => NodeWrapper.create(autoNode, root);
+
+    DesktopNode.findAndSetChildren(root, childConstructor);
+    return root;
+  }
+
+  /** @override */
+  static findAndSetChildren(root, childConstructor) {
+    const interestingChildren = RootNodeWrapper.getInterestingChildren(root);
+
+    if (interestingChildren.length < 1) {
+      throw SwitchAccess.error(
+          SAConstants.ErrorType.MALFORMED_DESKTOP,
+          'Desktop node must have at least 1 interesting child.');
+    }
+
+    root.children = interestingChildren.map(childConstructor);
+  }
+}
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
new file mode 100644
index 0000000..b53e4aa
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js
@@ -0,0 +1,40 @@
+// 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(['../switch_access_e2e_test_base.js']);
+
+/**
+ * @constructor
+ * @extends {SwitchAccessE2ETest}
+ */
+function SwitchAccessDesktopNodeTest() {
+  SwitchAccessE2ETest.call(this);
+}
+
+SwitchAccessDesktopNodeTest.prototype = {
+  __proto__: SwitchAccessE2ETest.prototype,
+};
+
+TEST_F('SwitchAccessDesktopNodeTest', 'Build', function() {
+  this.runWithLoadedTree('', (desktop) => {
+    const desktopNode = DesktopNode.build(desktop);
+
+    const children = desktopNode.children;
+    for (let i = 0; i < children.length; i++) {
+      const child = children[i];
+      // The desktop tree should not include a back button.
+      assertFalse(child instanceof BackButtonNode);
+
+      // Check that the children form a loop.
+      const next = children[(i + 1) % children.length];
+      assertEquals(
+          next, child.next, 'next not properly initialized on child ' + i);
+      // We add children.length to ensure the value is greater than zero.
+      const previous = children[(i - 1 + children.length) % children.length];
+      assertEquals(
+          previous, child.previous,
+          'previous not properly initialized on child ' + i);
+    }
+  });
+});
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js
index 834effc4..fa451a7 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js
@@ -39,7 +39,7 @@
   performAction(action) {
     switch (action) {
       case SAConstants.MenuAction.OPEN_KEYBOARD:
-        this.automationNode.focus();
+        NavigationManager.enterKeyboard();
         return SAConstants.ActionResponse.CLOSE_MENU;
       case SAConstants.MenuAction.DICTATION:
         chrome.accessibilityPrivate.toggleDictation();
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
index be8a03d..9d942a64 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
@@ -90,18 +90,32 @@
  */
 class KeyboardRootNode extends RootNodeWrapper {
   /**
-   * @param {!chrome.automation.AutomationNode} keyboard
+   * @param {!chrome.automation.AutomationNode} groupNode
    * @private
    */
-  constructor(keyboard) {
-    super(keyboard);
+  constructor(groupNode) {
+    super(groupNode);
   }
 
   // ================= General methods =================
 
+
+  /** @override */
+  isValidGroup() {
+    // To ensure we can find the keyboard root node to appropriately respond to
+    // visibility changes, never mark it as invalid.
+    return true;
+  }
+
   /** @override */
   onExit() {
-    chrome.accessibilityPrivate.setVirtualKeyboardVisible(false);
+    // If the keyboard is currently visible, ignore the corresponding
+    // state change.
+    if (KeyboardRootNode.isVisible_) {
+      KeyboardRootNode.explicitStateChange_ = true;
+      chrome.accessibilityPrivate.setVirtualKeyboardVisible(false);
+    }
+
     AutoScanManager.setInKeyboard(false);
   }
 
@@ -109,20 +123,23 @@
 
   /**
    * Creates the tree structure for the system menu.
-   * @param {!chrome.automation.AutomationNode} desktop
    * @return {!KeyboardRootNode}
    */
-  static buildTree(desktop) {
+  static buildTree() {
     KeyboardRootNode.loadKeyboard_();
     AutoScanManager.setInKeyboard(true);
 
-    const keyboardContainer =
-        desktop.find({role: chrome.automation.RoleType.KEYBOARD});
+    if (!KeyboardRootNode.keyboardObject_) {
+      throw SwitchAccess.error(
+          SAConstants.ErrorType.MISSING_KEYBOARD,
+          'Could not find keyboard in the automation tree');
+    }
     const keyboard =
-        new AutomationTreeWalker(keyboardContainer, constants.Dir.FORWARD, {
-          visit: (node) => SwitchAccessPredicate.isGroup(node, null),
-          root: (node) => node === keyboardContainer
-        })
+        new AutomationTreeWalker(
+            KeyboardRootNode.keyboardObject_, constants.Dir.FORWARD, {
+              visit: (node) => SwitchAccessPredicate.isGroup(node, null),
+              root: (node) => node === KeyboardRootNode.keyboardObject_
+            })
             .next()
             .node;
 
@@ -132,10 +149,68 @@
   }
 
   /**
+   * Start listening for keyboard open/closed.
+   */
+  static startWatchingVisibility() {
+    KeyboardRootNode.isVisible_ =
+        SwitchAccessPredicate.isVisible(KeyboardRootNode.keyboardObject_);
+
+    KeyboardRootNode.keyboardObject_.addEventListener(
+        chrome.automation.EventType.ARIA_ATTRIBUTE_CHANGED,
+        KeyboardRootNode.checkVisibilityChanged_, false /* capture */);
+  }
+
+  // ================= Private static methods =================
+
+  /**
+   * @param {chrome.automation.AutomationEvent} event
+   * @private
+   */
+  static checkVisibilityChanged_(event) {
+    const currentlyVisible =
+        SwitchAccessPredicate.isVisible(KeyboardRootNode.keyboardObject_);
+    if (currentlyVisible === KeyboardRootNode.isVisible_) {
+      return;
+    }
+
+    KeyboardRootNode.isVisible_ = currentlyVisible;
+
+    if (KeyboardRootNode.explicitStateChange_) {
+      // When the user has explicitly shown / hidden the keyboard, do not
+      // enter / exit the keyboard again to avoid looping / double-calls.
+      KeyboardRootNode.explicitStateChange_ = false;
+      return;
+    }
+
+    if (KeyboardRootNode.isVisible_) {
+      NavigationManager.enterKeyboard();
+    } else {
+      NavigationManager.exitKeyboard();
+    }
+  }
+
+  /**
+   * @return {chrome.automation.AutomationNode}
+   * @private
+   */
+  static get keyboardObject_() {
+    if (!this.object_ || !this.object_.role) {
+      this.object_ = NavigationManager.instance.desktopNode.find(
+          {role: chrome.automation.RoleType.KEYBOARD});
+    }
+    return this.object_;
+  }
+
+  /**
    * Loads the keyboard.
    * @private
    */
   static loadKeyboard_() {
+    if (KeyboardRootNode.isVisible_) {
+      return;
+    }
+
+    KeyboardRootNode.explicitStateChange_ = true;
     chrome.accessibilityPrivate.setVirtualKeyboardVisible(true);
   }
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
index 2db9f76..cf370a32 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
@@ -138,6 +138,7 @@
     switch (action) {
       case SAConstants.MenuAction.SELECT:
         this.baseNode_.doDefault();
+        return SAConstants.ActionResponse.CLOSE_MENU;
       case SAConstants.MenuAction.SCROLL_DOWN:
         ancestor = this.getScrollableAncestor_();
         if (ancestor.scrollable) {
@@ -301,7 +302,7 @@
 
   /**
    * Refreshes the children of this root node.
-   * @private
+   * @protected
    */
   refresh_() {
     // Find the currently focused child.
@@ -340,26 +341,6 @@
   // ================= Static methods =================
 
   /**
-   * @param {!AutomationNode} desktop
-   * @return {!RootNodeWrapper}
-   */
-  static buildDesktopTree(desktop) {
-    const root = new RootNodeWrapper(desktop);
-    const interestingChildren = RootNodeWrapper.getInterestingChildren(root);
-
-    if (interestingChildren.length < 1) {
-      throw SwitchAccess.error(
-          SAConstants.ErrorType.MALFORMED_DESKTOP,
-          'Desktop node must have at least 1 interesting child.');
-    }
-
-    const childConstructor = (autoNode) => NodeWrapper.create(autoNode, root);
-    root.children = interestingChildren.map(childConstructor);
-
-    return root;
-  }
-
-  /**
    * @param {!AutomationNode} rootNode
    * @return {!RootNodeWrapper}
    */
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper_test.js
index b8221b3..e213283d 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper_test.js
@@ -16,29 +16,6 @@
   __proto__: SwitchAccessE2ETest.prototype,
 };
 
-TEST_F('SwitchAccessNodeWrapperTest', 'BuildDesktopTree', function() {
-  this.runWithLoadedTree('', (desktop) => {
-    const desktopRootNode = RootNodeWrapper.buildDesktopTree(desktop);
-
-    const children = desktopRootNode.children;
-    for (let i = 0; i < children.length; i++) {
-      const child = children[i];
-      // The desktop tree should not include a back button.
-      assertFalse(child instanceof BackButtonNode);
-
-      // Check that the children form a loop.
-      const next = children[(i + 1) % children.length];
-      assertEquals(
-          next, child.next, 'next not properly initialized on child ' + i);
-      // We add children.length to ensure the value is greater than zero.
-      const previous = children[(i - 1 + children.length) % children.length];
-      assertEquals(
-          previous, child.previous,
-          'previous not properly initialized on child ' + i);
-    }
-  });
-});
-
 TEST_F('SwitchAccessNodeWrapperTest', 'AsRootNode', function() {
   const website = `<div aria-label="outer">
                      <div aria-label="inner">
@@ -75,46 +52,45 @@
 
 TEST_F('SwitchAccessNodeWrapperTest', 'Equals', function() {
   this.runWithLoadedTree('', (desktop) => {
-    const desktopRootNode = RootNodeWrapper.buildDesktopTree(desktop);
+    const desktopNode = DesktopNode.build(desktop);
 
-    let childGroup = desktopRootNode.firstChild;
+    let childGroup = desktopNode.firstChild;
     let i = 0;
-    while (!childGroup.isGroup() && i < desktopRootNode.children.length) {
+    while (!childGroup.isGroup() && i < desktopNode.children.length) {
       childGroup = childGroup.next;
       i++;
     }
     childGroup = childGroup.asRootNode();
 
-    assertFalse(desktopRootNode.equals(), 'Root node equals nothing');
+    assertFalse(desktopNode.equals(), 'Root node equals nothing');
     assertFalse(
-        desktopRootNode.equals(new SARootNode()),
+        desktopNode.equals(new SARootNode()),
         'Different type root nodes are equal');
     assertFalse(
-        new SARootNode().equals(desktopRootNode),
+        new SARootNode().equals(desktopNode),
         'Equals is not symmetric? Different types of root are equal');
     assertFalse(
-        desktopRootNode.equals(childGroup),
+        desktopNode.equals(childGroup),
         'Groups with different children are equal');
     assertFalse(
-        childGroup.equals(desktopRootNode),
+        childGroup.equals(desktopNode),
         'Equals is not symmetric? Groups with different children are equal');
 
     assertTrue(
-        desktopRootNode.equals(desktopRootNode),
+        desktopNode.equals(desktopNode),
         'Equals is not reflexive? (root node)');
-    const desktopCopy = RootNodeWrapper.buildDesktopTree(desktop);
+    const desktopCopy = DesktopNode.build(desktop);
     assertTrue(
-        desktopRootNode.equals(desktopCopy), 'Two desktop roots are not equal');
+        desktopNode.equals(desktopCopy), 'Two desktop roots are not equal');
     assertTrue(
-        desktopCopy.equals(desktopRootNode),
+        desktopCopy.equals(desktopNode),
         'Equals is not symmetric? Two desktop roots aren\'t equal');
 
-    const wrappedNode = desktopRootNode.firstChild;
+    const wrappedNode = desktopNode.firstChild;
     assertTrue(
         wrappedNode instanceof NodeWrapper,
         'Child node is not of type NodeWrapper');
-    assertGT(
-        desktopRootNode.children.length, 1, 'Desktop root has only 1 child');
+    assertGT(desktopNode.children.length, 1, 'Desktop root has only 1 child');
 
     assertFalse(wrappedNode.equals(), 'Child NodeWrapper equals nothing');
     assertFalse(
@@ -124,14 +100,14 @@
         new BackButtonNode().equals(wrappedNode),
         'Equals is not symmetric? NodeWrapper equals a BackButtonNode');
     assertFalse(
-        wrappedNode.equals(desktopRootNode.lastChild),
+        wrappedNode.equals(desktopNode.lastChild),
         'Children with different base nodes are equal');
     assertFalse(
-        desktopRootNode.lastChild.equals(wrappedNode),
+        desktopNode.lastChild.equals(wrappedNode),
         'Equals is not symmetric? Nodes with different base nodes are equal');
 
     const equivalentWrappedNode =
-        NodeWrapper.create(wrappedNode.baseNode_, desktopRootNode);
+        NodeWrapper.create(wrappedNode.baseNode_, desktopNode);
     assertTrue(
         wrappedNode.equals(wrappedNode),
         'Equals is not reflexive? (child node)');
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/preferences.js b/chrome/browser/resources/chromeos/accessibility/switch_access/preferences.js
index 9f05df5..623c353 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/preferences.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/preferences.js
@@ -6,14 +6,6 @@
  * Class to manage user preferences.
  */
 class SwitchAccessPreferences {
-  // =============== Static Methods ==============
-
-  static initialize() {
-    SwitchAccessPreferences.instance = new SwitchAccessPreferences();
-  }
-
-  // =============== Private Methods ==============
-
   /** @private */
   constructor() {
     /**
@@ -26,6 +18,14 @@
     this.init_();
   }
 
+  // =============== Static Methods ==============
+
+  static initialize() {
+    SwitchAccessPreferences.instance = new SwitchAccessPreferences();
+  }
+
+  // =============== Private Methods ==============
+
   /**
    * Get the boolean value for the given name, or |null| if the value is not a
    * boolean or does not exist.
@@ -68,6 +68,32 @@
   }
 
   /**
+   * Whether the current settings configuration is reasonably usable;
+   * specifically, whether there is a way to select and a way to navigate.
+   * @return {boolean}
+   * @private
+   */
+  settingsAreConfigured_() {
+    const selectSetting =
+        this.getNumber_(SAConstants.Preference.SELECT_SETTING);
+    const nextSetting = this.getNumber_(SAConstants.Preference.NEXT_SETTING);
+    const previousSetting =
+        this.getNumber_(SAConstants.Preference.PREVIOUS_SETTING);
+    const autoScanEnabled =
+        !!this.getBoolean_(SAConstants.Preference.AUTO_SCAN_ENABLED);
+
+    if (!selectSetting) {
+      return false;
+    }
+
+    if (nextSetting || previousSetting) {
+      return true;
+    }
+
+    return autoScanEnabled;
+  }
+
+  /**
    * Updates the cached preferences.
    * @param {!Array<chrome.settingsPrivate.PrefObject>} preferences
    * @param {boolean} isFirstLoad
@@ -76,7 +102,7 @@
   updateFromSettings_(preferences, isFirstLoad = false) {
     for (const pref of preferences) {
       // Ignore preferences that are not used by Switch Access.
-      if (!Object.values(SAConstants.Preference).includes(pref.key)) {
+      if (!this.usesPreference_(pref)) {
         continue;
       }
 
@@ -106,45 +132,17 @@
       }
     }
 
-    if (isFirstLoad) {
-      this.onInitialLoadComplete_();
-    }
-  }
-
-  /**
-   * Called when the preferences are finished loading for the first time.
-   * @private
-   */
-  onInitialLoadComplete_() {
-    if (!this.settingsAreConfigured_()) {
+    if (isFirstLoad && !this.settingsAreConfigured_()) {
       chrome.accessibilityPrivate.openSettingsSubpage(
           'manageAccessibility/switchAccess');
     }
   }
 
   /**
-   * Whether the current settings configuration is reasonably usable;
-   * specifically, whether there is a way to select and a way to navigate.
+   * @param {!chrome.settingsPrivate.PrefObject} pref
    * @return {boolean}
-   * @private
    */
-  settingsAreConfigured_() {
-    const selectSetting =
-        this.getNumber_(SAConstants.Preference.SELECT_SETTING);
-    const nextSetting = this.getNumber_(SAConstants.Preference.NEXT_SETTING);
-    const previousSetting =
-        this.getNumber_(SAConstants.Preference.PREVIOUS_SETTING);
-    const autoScanEnabled =
-        !!this.getBoolean_(SAConstants.Preference.AUTO_SCAN_ENABLED);
-
-    if (!selectSetting) {
-      return false;
-    }
-
-    if (nextSetting || previousSetting) {
-      return true;
-    }
-
-    return autoScanEnabled;
+  usesPreference_(pref) {
+    return Object.values(SAConstants.Preference).includes(pref.key);
   }
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
index 298f1b5..a8cfd85 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
@@ -15,8 +15,9 @@
       AutoScanManager.initialize();
       NavigationManager.initialize(desktop);
 
-      BackButtonNode.findAutomationNode(desktop);
+      BackButtonNode.findAutomationNode();
       Commands.initialize();
+      KeyboardRootNode.startWatchingVisibility();
       SwitchAccessPreferences.initialize();
     });
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js
index 850f69a..f18498e 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js
@@ -69,6 +69,7 @@
     NO_CHILDREN: 7,
     MALFORMED_DESKTOP: 8,
     MISSING_LOCATION: 9,
+    MISSING_KEYBOARD: 10,
   },
 
   /**
diff --git a/chrome/browser/resources/downloads/constants.js b/chrome/browser/resources/downloads/constants.js
index a38d1c5..ed08b72 100644
--- a/chrome/browser/resources/downloads/constants.js
+++ b/chrome/browser/resources/downloads/constants.js
@@ -35,4 +35,5 @@
   DANGEROUS: 'DANGEROUS',
   INTERRUPTED: 'INTERRUPTED',
   MIXED_CONTENT: 'MIXED_CONTENT',
+  ASYNC_SCANNING: 'ASYNC_SCANNING',
 };
diff --git a/chrome/browser/resources/downloads/item.html b/chrome/browser/resources/downloads/item.html
index cd94017..9b20d00 100644
--- a/chrome/browser/resources/downloads/item.html
+++ b/chrome/browser/resources/downloads/item.html
@@ -135,27 +135,34 @@
     opacity: .5;
   }
 
-  #file-icon-wrapper iron-icon[icon='cr:insert-drive-file'] {
+  #file-icon-wrapper iron-icon[icon-color='paper-grey'] {
     color: var(--paper-grey-400);
   }
 
-  #file-icon-wrapper iron-icon[icon='cr:warning'],
-  .dangerous #description {
+  #file-icon-wrapper iron-icon[icon-color='red'] {
     color: var(--google-red-700);
   }
 
-  #file-icon-wrapper iron-icon[icon='cr:error'],
-  .dangerous #description {
+  #file-icon-wrapper iron-icon[icon-color='yellow'] {
     color: var(--google-yellow-500);
   }
 
   @media (prefers-color-scheme: dark) {
-    #file-icon-wrapper iron-icon[icon='cr:warning'],
-    .dangerous #description {
+    #file-icon-wrapper iron-icon[icon-color='red'] {
       color: var(--google-red-refresh-300);
     }
   }
 
+  #file-icon-wrapper iron-icon[icon-color='grey'] {
+    color: var(--google-grey-700);
+  }
+
+  @media (prefers-color-scheme: dark) {
+    #file-icon-wrapper iron-icon[icon-color='grey'] {
+      color: var(--google-grey-500);
+    }
+  }
+
   #name,
   #file-link,
   #url {
@@ -269,7 +276,8 @@
   }
 
   #pauseOrResume,
-  #dangerous .action-button {
+  #dangerous .action-button,
+  #openNow {
     margin-inline-end: 8px;
   }
 </style>
@@ -286,10 +294,13 @@
     attribute and remove aria-hidden="true" from #file-icon-wrapper
   -->
   <div id="file-icon-wrapper" class="icon-wrapper" aria-hidden="true">
-    <img class="icon" id="file-icon" alt="" hidden="[[!useFileIcon_]]">
+    <img class="icon" id="file-icon" alt="" hidden="[[!useFileIcon_]]"
+    icon-color$="[[computeIconColor_(isDangerous_, data.dangerType,
+    useFileIcon_)]]">
     <iron-icon class="icon" icon$="[[computeIcon_(
         isDangerous_, data.dangerType, useFileIcon_)]]"
-        hidden="[[useFileIcon_]]"></iron-icon>
+        hidden="[[useFileIcon_]]" icon-color$="[[computeIconColor_(isDangerous_,
+        data.dangerType, useFileIcon_)]]"></iron-icon>
   </div>
 
   <div id="details">
@@ -351,6 +362,14 @@
           </cr-button>
         </div>
       </template>
+      <template is="dom-if" if="[[showOpenNow_]]">
+        <div role="gridcell">
+          <cr-button on-click="onOpenNowTap_" id="openNow" class="action-button"
+                     focus-row-control focus-type="open">
+            $i18n{controlOpenNow}
+          </cr-button>
+        </div>
+      </template>
       <template is="dom-if" if="[[showCancel_]]">
         <div role="gridcell">
           <cr-button on-click="onCancelTap_" focus-row-control
diff --git a/chrome/browser/resources/downloads/item.js b/chrome/browser/resources/downloads/item.js
index adbc96a..e5d8ca9 100644
--- a/chrome/browser/resources/downloads/item.js
+++ b/chrome/browser/resources/downloads/item.js
@@ -116,6 +116,13 @@
         value: false,
       },
 
+      /** @private */
+      showOpenNow_: {
+        computed: 'computeShowOpenNow_(data.state)',
+        type: Boolean,
+        value: false,
+      },
+
       useFileIcon_: Boolean,
     },
 
@@ -289,6 +296,9 @@
           }
           break;
 
+        case States.ASYNC_SCANNING:
+          return loadTimeData.getString('asyncScanningDownloadDesc');
+
         case States.IN_PROGRESS:
         case States.PAUSED:  // Fallthrough.
           return data.progressStatusText;
@@ -314,7 +324,6 @@
     computeIcon_() {
       if (this.data) {
         const dangerType = this.data.dangerType;
-
         if ((loadTimeData.getBoolean('requestsApVerdicts') &&
              dangerType === DangerType.UNCOMMON_CONTENT) ||
             dangerType === DangerType.SENSITIVE_CONTENT_WARNING) {
@@ -329,6 +338,10 @@
         if (WARNING_TYPES.includes(dangerType)) {
           return 'cr:warning';
         }
+
+        if (this.data.state === States.ASYNC_SCANNING) {
+          return 'cr:error';
+        }
       }
       if (this.isDangerous_) {
         return 'cr:warning';
@@ -340,6 +353,41 @@
     },
 
     /**
+     * @return {string}
+     * @private
+     */
+    computeIconColor_() {
+      if (this.data) {
+        const dangerType = this.data.dangerType;
+        if ((loadTimeData.getBoolean('requestsApVerdicts') &&
+             dangerType === DangerType.UNCOMMON_CONTENT) ||
+            dangerType === DangerType.SENSITIVE_CONTENT_WARNING) {
+          return 'yellow';
+        }
+
+        const WARNING_TYPES = [
+          DangerType.SENSITIVE_CONTENT_BLOCK,
+          DangerType.BLOCKED_TOO_LARGE,
+          DangerType.BLOCKED_PASSWORD_PROTECTED,
+        ];
+        if (WARNING_TYPES.includes(dangerType)) {
+          return 'red';
+        }
+
+        if (this.data.state === States.ASYNC_SCANNING) {
+          return 'grey';
+        }
+      }
+      if (this.isDangerous_) {
+        return 'red';
+      }
+      if (!this.useFileIcon_) {
+        return 'paper-grey';
+      }
+      return '';
+    },
+
+    /**
      * @return {boolean}
      * @private
      */
@@ -432,7 +480,8 @@
      */
     computeShowCancel_() {
       return this.data.state === States.IN_PROGRESS ||
-          this.data.state === States.PAUSED;
+          this.data.state === States.PAUSED ||
+          this.data.state === States.ASYNC_SCANNING;
     },
 
     /**
@@ -440,7 +489,16 @@
      * @private
      */
     computeShowProgress_() {
-      return this.showCancel_ && this.data.percent >= -1;
+      return this.showCancel_ && this.data.percent >= -1 &&
+          this.data.state !== States.ASYNC_SCANNING;
+    },
+
+    /**
+     * @return {boolean}
+     * @private
+     */
+    computeShowOpenNow_() {
+      return this.data.state === States.ASYNC_SCANNING;
     },
 
     /**
@@ -499,13 +557,16 @@
         this.useFileIcon_ = false;
       } else if (OVERRIDDEN_ICON_TYPES.includes(this.data.dangerType)) {
         this.useFileIcon_ = false;
+      } else if (this.data.state === States.ASYNC_SCANNING) {
+        this.useFileIcon_ = false;
       } else {
         this.$.url.href = assert(this.data.url);
         const path = this.data.filePath;
         IconLoader.getInstance()
             .loadIcon(this.$['file-icon'], path)
             .then(success => {
-              if (path === this.data.filePath) {
+              if (path === this.data.filePath && this.data.state !==
+                  States.ASYNC_SCANNING) {
                 this.useFileIcon_ = success;
               }
             });
@@ -523,6 +584,11 @@
       this.mojoHandler_.discardDangerous(this.data.id);
     },
 
+    /** @private */
+    onOpenNowTap_() {
+      this.mojoHandler_.openDuringScanningRequiringGesture(this.data.id);
+    },
+
     /**
      * @private
      * @param {Event} e
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 9f3aedc..18b74b7 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -985,6 +985,12 @@
                  file="site_settings_page/site_settings_page.js"
                  type="chrome_html"
                  preprocess="true" />
+      <structure name="IDR_SETTINGS_SITE_SETTINGS_LIST_HTML"
+                 file="site_settings_page/site_settings_list.html"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_SITE_SETTINGS_LIST_JS"
+                 file="site_settings_page/site_settings_list.js"
+                 type="chrome_html" />
       <structure name="IDR_SETTINGS_SITE_SETTINGS_PREFS_BROWSER_PROXY_HTML"
                  file="site_settings/site_settings_prefs_browser_proxy.html"
                  type="chrome_html" />
diff --git a/chrome/browser/resources/settings/site_settings_page/BUILD.gn b/chrome/browser/resources/settings/site_settings_page/BUILD.gn
index fd26e1fd..07effed 100644
--- a/chrome/browser/resources/settings/site_settings_page/BUILD.gn
+++ b/chrome/browser/resources/settings/site_settings_page/BUILD.gn
@@ -7,6 +7,7 @@
 js_type_check("closure_compile") {
   deps = [
     ":recent_site_permissions",
+    ":site_settings_list",
     ":site_settings_page",
   ]
 }
@@ -29,12 +30,20 @@
     "..:route",
     "..:router",
     "../site_settings:constants",
-    "../site_settings:site_settings_behavior",
-    "../site_settings:site_settings_prefs_browser_proxy",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:cr",
-    "//ui/webui/resources/js:i18n_behavior",
     "//ui/webui/resources/js:load_time_data",
+    "//ui/webui/resources/js/cr/ui:focus_without_ink",
+  ]
+}
+
+js_library("site_settings_list") {
+  deps = [
+    "..:route",
+    "../site_settings:constants",
+    "../site_settings:site_settings_prefs_browser_proxy",
+    "//ui/webui/resources/js:assert",
+    "//ui/webui/resources/js:i18n_behavior",
     "//ui/webui/resources/js:web_ui_listener_behavior",
     "//ui/webui/resources/js/cr/ui:focus_without_ink",
   ]
@@ -43,9 +52,20 @@
 # TODO(crbug.com/1026426): Fix and enable.
 #js_type_check("closure_compile_module") {
 #  is_polymer3 = true
-#  deps = [ ":site_settings_page.m" ]
+#  deps = [
+#    ":site_settings_list.m",
+#    ":site_settings_page.m",
+# ]
 #}
 
+js_library("site_settings_list.m") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings_page/site_settings_list.m.js" ]
+  deps = [
+    # TODO: Fill those in.
+  ]
+  extra_deps = [ ":site_settings_list_module" ]
+}
+
 js_library("site_settings_page.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings_page/site_settings_page.m.js" ]
   deps = [
@@ -57,7 +77,16 @@
 import("//tools/polymer/polymer.gni")
 
 group("polymer3_elements") {
-  deps = [ ":site_settings_page_module" ]
+  deps = [
+    ":site_settings_list_module",
+    ":site_settings_page_module",
+  ]
+}
+
+polymer_modulizer("site_settings_list") {
+  js_file = "site_settings_list.js"
+  html_file = "site_settings_list.html"
+  html_type = "dom-module"
 }
 
 polymer_modulizer("site_settings_page") {
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_list.html b/chrome/browser/resources/settings/site_settings_page/site_settings_list.html
new file mode 100644
index 0000000..60862be
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_list.html
@@ -0,0 +1,33 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="../icons.html">
+<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="../site_settings/site_settings_prefs_browser_proxy.html">
+
+<dom-module id="settings-site-settings-list">
+  <template>
+    <style include="settings-shared">
+      cr-link-row {
+        --cr-icon-button-margin-start: 20px;
+      }
+
+      /* Remove border-top added by .hr for the 1st cr-link-row. */
+      cr-link-row:first-of-type {
+        border-top: none;
+      }
+    </style>
+    <template is="dom-repeat" items="[[categoryList]]">
+      <cr-link-row class="hr two-line" data-route$="[[item.route]]"
+          id="[[item.id]]" label="[[i18n(item.label)]]"
+          on-click="onClick_" start-icon="[[item.icon]]"
+          sub-label="[[item.subLabel]]"
+          role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row>
+    </template>
+  </template>
+  <script src="site_settings_list.js"></script>
+</dom-template>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_list.js b/chrome/browser/resources/settings/site_settings_page/site_settings_list.js
new file mode 100644
index 0000000..6e995006
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_list.js
@@ -0,0 +1,148 @@
+// 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.
+
+cr.define('settings', function() {
+  /**
+   * @param {string} setting Value from settings.ContentSetting.
+   * @param {string} enabled Non-block label ('feature X not allowed').
+   * @param {string} disabled Block label (likely just, 'Blocked').
+   * @param {?string} other Tristate value (maybe, 'session only').
+   */
+  function defaultSettingLabel(setting, enabled, disabled, other) {
+    if (setting == settings.ContentSetting.BLOCK) {
+      return disabled;
+    }
+    if (setting == settings.ContentSetting.ALLOW) {
+      return enabled;
+    }
+
+    return other || enabled;
+  }
+
+  Polymer({
+    is: 'settings-site-settings-list',
+
+    behaviors: [WebUIListenerBehavior, I18nBehavior],
+
+    properties: {
+      /** @type {!Array<!settings.CategoryListItem>} */
+      categoryList: Array,
+
+      /** @type {!Map<string, (string|Function)>} */
+      focusConfig: {
+        type: Object,
+        observer: 'focusConfigChanged_',
+      },
+    },
+
+    /** @type {?settings.SiteSettingsPrefsBrowserProxy} */
+    browserProxy: null,
+
+    /**
+     * @param {!Map<string, string>} newConfig
+     * @param {?Map<string, string>} oldConfig
+     * @private
+     */
+    focusConfigChanged_(newConfig, oldConfig) {
+      // focusConfig is set only once on the parent, so this observer should
+      // only fire once.
+      assert(!oldConfig);
+
+      // Populate the |focusConfig| map of the parent <settings-animated-pages>
+      // element, with additional entries that correspond to subpage trigger
+      // elements residing in this element's Shadow DOM.
+      for (const item of this.categoryList) {
+        const route = settings.routes[item.route];
+        this.focusConfig.set(route.path, () => this.async(() => {
+          cr.ui.focusWithoutInk(assert(this.$$(`#${item.id}`)));
+        }));
+      }
+    },
+
+    /** @override */
+    ready() {
+      this.browserProxy_ =
+          settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
+
+      for (const item of this.categoryList) {
+        // Default labels are not applicable to ZOOM_LEVELS or PDF.
+        if (item.id === settings.ContentSettingsTypes.ZOOM_LEVELS ||
+            item.id === 'pdfDocuments') {
+          continue;
+        }
+
+        this.refreshDefaultValueLabel_(item.id);
+      }
+
+      this.addWebUIListener(
+          'contentSettingCategoryChanged',
+          this.refreshDefaultValueLabel_.bind(this));
+
+      const hasProtocolHandlers = this.categoryList.some(item => {
+        return item.id === settings.ContentSettingsTypes.PROTOCOL_HANDLERS;
+      });
+
+      if (hasProtocolHandlers) {
+        // The protocol handlers have a separate enabled/disabled notifier.
+        this.addWebUIListener('setHandlersEnabled', enabled => {
+          this.updateDefaultValueLabel_(
+              settings.ContentSettingsTypes.PROTOCOL_HANDLERS,
+              enabled ? settings.ContentSetting.ALLOW :
+                        settings.ContentSetting.BLOCK);
+        });
+        this.browserProxy_.observeProtocolHandlersEnabledState();
+      }
+    },
+
+    /**
+     * @param {!settings.ContentSettingsTypes} category The category to refresh
+     *     (fetch current value + update UI)
+     * @private
+     */
+    refreshDefaultValueLabel_(category) {
+      this.browserProxy_.getDefaultValueForContentType(category).then(
+          defaultValue => {
+            this.updateDefaultValueLabel_(category, defaultValue.setting);
+          });
+    },
+
+    /**
+     * Updates the DOM for the given |category| to display a label that
+     * corresponds to the given |setting|.
+     * @param {!settings.ContentSettingsTypes} category
+     * @param {!settings.ContentSetting} setting
+     * @private
+     */
+    updateDefaultValueLabel_(category, setting) {
+      const element = this.$$(`#${category}`);
+      if (!element) {
+        // |category| is not part of this list.
+        return;
+      }
+
+      const index = this.$$('dom-repeat').indexForElement(element);
+      const dataItem = this.categoryList[index];
+      this.set(
+          `categoryList.${index}.subLabel`,
+          defaultSettingLabel(
+              setting,
+              dataItem.enabledLabel ? this.i18n(dataItem.enabledLabel) : '',
+              dataItem.disabledLabel ? this.i18n(dataItem.disabledLabel) : '',
+              dataItem.otherLabel ? this.i18n(dataItem.otherLabel) : null));
+    },
+
+    /**
+     * @param {!Event} event
+     * @private
+     */
+    onClick_(event) {
+      const dataSet =
+          /** @type {{route: string}} */ (event.currentTarget.dataset);
+      this.fire('site-settings-item-click', dataSet.route);
+    },
+  });
+
+  // #cr_define_end
+  return {defaultSettingLabel};
+});
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
index 466070f..63996020 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -1,37 +1,20 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="../icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../router.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../site_settings/constants.html">
-<link rel="import" href="../site_settings/site_settings_behavior.html">
-<link rel="import" href="../site_settings/site_settings_prefs_browser_proxy.html">
-<link rel="import" href="recent_site_permissions.html">
 <link rel="import" href="../metrics_browser_proxy.html">
+<link rel="import" href="recent_site_permissions.html">
+<link rel="import" href="site_settings_list.html">
 
 <dom-module id="settings-site-settings-page">
   <template>
-    <style include="settings-shared">
-      cr-link-row {
-        --cr-icon-button-margin-start: 20px;
-      }
-
-      /* Add min-height to prevent shifting as sublabels load. */
-      .two-line {
-        --cr-section-min-height: var(--cr-section-two-line-min-height);
-      }
-
-      /* Remove border-top added by .hr for the 1st cr-link-row. */
-      .settings-box + cr-link-row {
-        border-top: none;
-      }
-    </style>
+    <style include="settings-shared"></style>
     <template is="dom-if" if="[[!privacySettingsRedesignEnabled_]]">
       <div class="settings-box first line-only">
         <h2 class="first">$i18n{siteSettingsAllSites}</h2>
@@ -50,18 +33,57 @@
     <cr-link-row data-route="SITE_SETTINGS_ALL" id="allSites"
         class$="[[getClassForSiteSettingsAllLink_(noRecentSitePermissions_)]]"
         label="$i18n{siteSettingsAllSitesDescription}"
-        on-click="onTapNavigate_"
+        on-click="onSiteSettingsAllClick_"
         role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row>
     <div class="settings-box first line-only">
       <h2>$i18n{siteSettingsPermissions}</h2>
     </div>
 
-    <template is="dom-repeat" items="[[categoryList_]]">
-      <cr-link-row class="hr two-line" data-route$="[[item.route]]"
-          id="[[item.id]]" label="[[i18n(item.label)]]"
-          on-click="onTapNavigate_" start-icon="[[item.icon]]"
-          sub-label="[[item.subLabel]]"
-          role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row>
+    <template is="dom-if" if="[[!privacySettingsRedesignEnabled_]]">
+      <settings-site-settings-list
+          category-list="[[lists_.all]]"
+          focus-config="[[focusConfig]]"
+          on-site-settings-item-click="onSiteSettingsItemClick_">
+      </settings-site-settings-list>
+    </template>
+
+    <template is="dom-if" if="[[privacySettingsRedesignEnabled_]]">
+      <settings-site-settings-list
+          category-list="[[lists_.permissionsBasic]]"
+          focus-config="[[focusConfig]]"
+          on-site-settings-item-click="onSiteSettingsItemClick_">
+      </settings-site-settings-list>
+      <cr-expand-button class="settings-box"
+          expanded="{{permissionsExpanded_}}">
+        <div>$i18n{siteSettingsPermissionsMore}</div>
+      </cr-expand-button>
+      <iron-collapse opened="[[permissionsExpanded_]]">
+        <settings-site-settings-list
+            category-list="[[lists_.permissionsAdvanced]]"
+            focus-config="[[focusConfig]]"
+            on-site-settings-item-click="onSiteSettingsItemClick_">
+        </settings-site-settings-list>
+      </iron-collapse>
+
+      <div class="settings-box first line-only">
+        <h2>$i18n{siteSettingsContent}</h2>
+      </div>
+      <settings-site-settings-list
+          category-list="[[lists_.contentBasic]]"
+          focus-config="[[focusConfig]]"
+          on-site-settings-item-click="onSiteSettingsItemClick_">
+      </settings-site-settings-list>
+      <cr-expand-button class="settings-box"
+          expanded="{{contentExpanded_}}">
+        <div>$i18n{siteSettingsContentMore}</div>
+      </cr-expand-button>
+      <iron-collapse opened="[[contentExpanded_]]">
+        <settings-site-settings-list
+            category-list="[[lists_.contentAdvanced]]"
+            focus-config="[[focusConfig]]"
+            on-site-settings-item-click="onSiteSettingsItemClick_">
+        </settings-site-settings-list>
+      </iron-collapse>
     </template>
   </template>
   <script src="site_settings_page.js"></script>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
index 8977c56..e58ebd7 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -10,23 +10,6 @@
 
 cr.define('settings', function() {
   /**
-   * @param {string} setting Value from settings.ContentSetting.
-   * @param {string} enabled Non-block label ('feature X not allowed').
-   * @param {string} disabled Block label (likely just, 'Blocked').
-   * @param {?string} other Tristate value (maybe, 'session only').
-   * @private
-   */
-  function defaultSettingLabel(setting, enabled, disabled, other) {
-    if (setting == settings.ContentSetting.BLOCK) {
-      return disabled;
-    }
-    if (setting == settings.ContentSetting.ALLOW) {
-      return enabled;
-    }
-    return other || enabled;
-  }
-
-  /**
    * @typedef{{
    *   route: string,
    *   id: settings.ContentSettingsTypes,
@@ -40,11 +23,20 @@
    */
   let CategoryListItem;
 
+  const Id = settings.ContentSettingsTypes;
+
+  /**
+   * @type {?Map<!settings.ContentSettingsTypes, !settings.CategoryListItem>}
+   */
+  let categoryItemMap = null;
+
   /**
    * @return {!Map<!settings.ContentSettingsTypes, !settings.CategoryListItem>}
    */
-  function buildCategoryItemMap() {
-    const Id = settings.ContentSettingsTypes;
+  function getCategoryItemMap() {
+    if (categoryItemMap !== null) {
+      return categoryItemMap;
+    }
 
     // The following list is ordered alphabetically by |id|. The order in which
     // these appear in the UI is determined elsewhere in this file.
@@ -302,69 +294,126 @@
       },
     ];
 
-    return new Map(categoryList.map(item => [item.id, item]));
+    categoryItemMap = new Map(categoryList.map(item => [item.id, item]));
+    return categoryItemMap;
+  }
+
+  /**
+   * @param {!Array<!settings.ContentSettingsTypes>} orderedIdList
+   * @return {!Array<!settings.CategoryListItem>}
+   */
+  function buildItemListFromIds(orderedIdList) {
+    const map = getCategoryItemMap();
+    const orderedList = [];
+    for (const id of orderedIdList) {
+      const item = map.get(id);
+      if (item.shouldShow === undefined || item.shouldShow()) {
+        orderedList.push(item);
+      }
+    }
+    return orderedList;
   }
 
   Polymer({
     is: 'settings-site-settings-page',
 
-    behaviors: [
-      SiteSettingsBehavior, WebUIListenerBehavior, I18nBehavior,
-      settings.RouteObserverBehavior
-    ],
+    behaviors: [settings.RouteObserverBehavior],
 
     properties: {
-      /** @private {!Array<!settings.CategoryListItem>} */
-      categoryList_: {
-        type: Array,
+      /**
+       * @private {{
+       *   all: (!Array<!settings.CategoryListItem>|undefined),
+       *   permissionsBasic: (!Array<!settings.CategoryListItem>|undefined),
+       *   permissionsAdvanced: (!Array<!settings.CategoryListItem>|undefined),
+       *   contentBasic: (!Array<!settings.CategoryListItem>|undefined),
+       *   contentAdvanced: (!Array<!settings.CategoryListItem>|undefined)
+       * }}
+       */
+      lists_: {
+        type: Object,
         value: function() {
-          const Id = settings.ContentSettingsTypes;
-          // Ordered according to how these should appear in the UI.
-          const orderedIdList = [
-            Id.COOKIES,
-            Id.GEOLOCATION,
-            Id.CAMERA,
-            Id.MIC,
-            Id.SENSORS,
-            Id.NOTIFICATIONS,
-            Id.JAVASCRIPT,
-            Id.PLUGINS,
-            Id.IMAGES,
-            Id.POPUPS,
-            Id.ADS,
-            Id.BACKGROUND_SYNC,
-            Id.SOUND,
-            Id.AUTOMATIC_DOWNLOADS,
-            Id.UNSANDBOXED_PLUGINS,
-            Id.PROTOCOL_HANDLERS,
-            Id.MIDI_DEVICES,
-            Id.ZOOM_LEVELS,
-            Id.USB_DEVICES,
-            Id.SERIAL_PORTS,
-            Id.NATIVE_FILE_SYSTEM_WRITE,
-            Id.HID_DEVICES,
-            'pdfDocuments',
-            // <if expr="chromeos">
-            Id.PROTECTED_CONTENT,
-            // </if>
-            Id.CLIPBOARD,
-            Id.PAYMENT_HANDLER,
-            Id.MIXEDSCRIPT,
-            Id.BLUETOOTH_SCANNING,
-            Id.AR,
-            Id.VR,
-          ];
-
-          const map = buildCategoryItemMap();
-          const orderedList = [];
-          for (const id of orderedIdList) {
-            const item = map.get(id);
-            if (item.shouldShow === undefined || item.shouldShow()) {
-              orderedList.push(item);
-            }
+          if (!loadTimeData.getBoolean('privacySettingsRedesignEnabled')) {
+            return {
+              all: buildItemListFromIds([
+                Id.COOKIES,
+                Id.GEOLOCATION,
+                Id.CAMERA,
+                Id.MIC,
+                Id.SENSORS,
+                Id.NOTIFICATIONS,
+                Id.JAVASCRIPT,
+                Id.PLUGINS,
+                Id.IMAGES,
+                Id.POPUPS,
+                Id.ADS,
+                Id.BACKGROUND_SYNC,
+                Id.SOUND,
+                Id.AUTOMATIC_DOWNLOADS,
+                Id.UNSANDBOXED_PLUGINS,
+                Id.PROTOCOL_HANDLERS,
+                Id.MIDI_DEVICES,
+                Id.ZOOM_LEVELS,
+                Id.USB_DEVICES,
+                Id.SERIAL_PORTS,
+                Id.NATIVE_FILE_SYSTEM_WRITE,
+                Id.HID_DEVICES,
+                'pdfDocuments',
+                // <if expr="chromeos">
+                Id.PROTECTED_CONTENT,
+                // </if>
+                Id.CLIPBOARD,
+                Id.PAYMENT_HANDLER,
+                Id.MIXEDSCRIPT,
+                Id.BLUETOOTH_SCANNING,
+                Id.AR,
+                Id.VR,
+              ]),
+            };
           }
-          return orderedList;
-        },
+
+          return {
+            permissionsBasic: buildItemListFromIds([
+              Id.GEOLOCATION,
+              Id.CAMERA,
+              Id.MIC,
+              Id.NOTIFICATIONS,
+              Id.BACKGROUND_SYNC,
+            ]),
+            permissionsAdvanced: buildItemListFromIds([
+              Id.SENSORS,
+              Id.AUTOMATIC_DOWNLOADS,
+              Id.UNSANDBOXED_PLUGINS,
+              Id.PROTOCOL_HANDLERS,
+              Id.MIDI_DEVICES,
+              Id.USB_DEVICES,
+              Id.SERIAL_PORTS,
+              Id.NATIVE_FILE_SYSTEM_WRITE,
+              Id.HID_DEVICES,
+              Id.CLIPBOARD,
+              Id.PAYMENT_HANDLER,
+              Id.BLUETOOTH_SCANNING,
+              Id.AR,
+              Id.VR,
+            ]),
+            contentBasic: buildItemListFromIds([
+              Id.COOKIES,
+              Id.JAVASCRIPT,
+              Id.PLUGINS,
+              Id.IMAGES,
+              Id.POPUPS,
+            ]),
+            contentAdvanced: buildItemListFromIds([
+              Id.SOUND,
+              Id.ADS,
+              Id.ZOOM_LEVELS,
+              'pdfDocuments',
+              // <if expr="chromeos">
+              Id.PROTECTED_CONTENT,
+              // </if>
+              Id.MIXEDSCRIPT,
+            ]),
+          };
+        }
       },
 
       /** @type {!Map<string, (string|Function)>} */
@@ -376,13 +425,19 @@
       /** @private */
       privacySettingsRedesignEnabled_: {
         type: Boolean,
-        value: loadTimeData.getBoolean('privacySettingsRedesignEnabled'),
+        value: function() {
+          return loadTimeData.getBoolean('privacySettingsRedesignEnabled');
+        },
       },
 
+      /** @private */
+      permissionsExpanded_: Boolean,
+
+      /** @private */
+      contentExpanded_: Boolean,
+
       /* @private */
-      noRecentSitePermissions_: {
-        type: Boolean,
-      },
+      noRecentSitePermissions_: Boolean,
     },
 
     /**
@@ -394,89 +449,22 @@
       // focusConfig is set only once on the parent, so this observer should
       // only fire once.
       assert(!oldConfig);
-
-      // Populate the |focusConfig| map of the parent <settings-animated-pages>
-      // element, with additional entries that correspond to subpage trigger
-      // elements residing in this element's Shadow DOM.
-
-      // Register the allSites route manually, since it is not part of the
-      // |categoryList_|.
-      /** @type {!Array<{id: string, route: string}>} */ const list =
-          this.categoryList_.slice();
-      list.push({id: 'allSites', route: 'SITE_SETTINGS_ALL'});
-
-      for (const item of list) {
-        const route = settings.routes[item.route];
-        this.focusConfig.set(route.path, () => this.async(() => {
-          cr.ui.focusWithoutInk(assert(this.$$(`#${item.id}`)));
-        }));
-      }
-    },
-
-    /** @override */
-    ready() {
-      this.metricsBrowserProxy_ =
-          settings.MetricsBrowserProxyImpl.getInstance();
-
-      for (const item of this.categoryList_) {
-        // Default labels are not applicable to ZOOM_LEVELS or PDF.
-        if (item.id === settings.ContentSettingsTypes.ZOOM_LEVELS ||
-            item.id === 'pdfDocuments') {
-          continue;
-        }
-
-        this.refreshDefaultValueLabel_(item.id);
-      }
-
-      this.addWebUIListener(
-          'contentSettingCategoryChanged',
-          this.refreshDefaultValueLabel_.bind(this));
-
-      // The protocol handlers have a separate enabled/disabled notifier.
-      this.addWebUIListener('setHandlersEnabled', enabled => {
-        this.updateDefaultValueLabel_(
-            settings.ContentSettingsTypes.PROTOCOL_HANDLERS,
-            enabled ? settings.ContentSetting.ALLOW :
-                      settings.ContentSetting.BLOCK);
+      this.focusConfig.set(settings.routes.SITE_SETTINGS_ALL.path, () => {
+        cr.ui.focusWithoutInk(assert(this.$$('#allSites')));
       });
-      this.browserProxy.observeProtocolHandlersEnabledState();
+    },
+
+    /** @private */
+    onSiteSettingsAllClick_(event) {
+      this.navigateToRoute_('SITE_SETTINGS_ALL');
     },
 
     /**
-     * @param {!settings.ContentSettingsTypes} category The category to refresh
-     *     (fetch current value + update UI)
+     * @param {!CustomEvent<string>} event
      * @private
      */
-    refreshDefaultValueLabel_(category) {
-      this.browserProxy.getDefaultValueForContentType(category).then(
-          defaultValue => {
-            this.updateDefaultValueLabel_(category, defaultValue.setting);
-          });
-    },
-
-    /**
-     * Updates the DOM for the given |category| to display a label that
-     * corresponds to the given |setting|.
-     * @param {!settings.ContentSettingsTypes} category
-     * @param {!settings.ContentSetting} setting
-     * @private
-     */
-    updateDefaultValueLabel_(category, setting) {
-      if (!this.isConnected) {
-        // Do nothing if the element has been detached from the DOM (happens in
-        // tests).
-        return;
-      }
-
-      const element = this.$$(`#${category}`);
-      const index = this.$$('dom-repeat').indexForElement(element);
-      const dataItem = this.categoryList_[index];
-      const subLabel = defaultSettingLabel(
-          setting,
-          dataItem.enabledLabel ? this.i18n(dataItem.enabledLabel) : '',
-          dataItem.disabledLabel ? this.i18n(dataItem.disabledLabel) : '',
-          dataItem.otherLabel ? this.i18n(dataItem.otherLabel) : null);
-      this.set(`categoryList_.${index}.subLabel`, subLabel);
+    onSiteSettingsItemClick_(event) {
+      this.navigateToRoute_(event.detail);
     },
 
     /**
@@ -510,18 +498,17 @@
 
     /**
      * Navigate to the route specified in the event dataset.
-     * @param {!Event} event The tap event.
+     * @param {string} routeName The name of the route to navigate to.
      * @private
      */
-    onTapNavigate_(event) {
-      const dataSet =
-          /** @type {{route: string}} */ (event.currentTarget.dataset);
-      this.metricsBrowserProxy_.recordSettingsPageHistogram(
-          settings.SettingsPageInteractions['PRIVACY_' + dataSet.route]);
-      settings.Router.getInstance().navigateTo(settings.routes[dataSet.route]);
+    navigateToRoute_(routeName) {
+      settings.MetricsBrowserProxyImpl.getInstance()
+          .recordSettingsPageHistogram(
+              settings.SettingsPageInteractions['PRIVACY_' + routeName]);
+      settings.Router.getInstance().navigateTo(settings.routes[routeName]);
     },
   });
 
   // #cr_define_end
-  return {CategoryListItem, defaultSettingLabel};
+  return {CategoryListItem};
 });
diff --git a/chrome/browser/safe_browsing/android/services_delegate_android.cc b/chrome/browser/safe_browsing/android/services_delegate_android.cc
index f241a4b..5bfd0de 100644
--- a/chrome/browser/safe_browsing/android/services_delegate_android.cc
+++ b/chrome/browser/safe_browsing/android/services_delegate_android.cc
@@ -103,11 +103,6 @@
   database_manager_->StopOnIOThread(shutdown);
 }
 
-void ServicesDelegateAndroid::OnProfileWillBeDestroyedOnIOThread(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
-  database_manager_->OnProfileWillBeDestroyedOnIOThread(url_loader_factory);
-}
-
 void ServicesDelegateAndroid::CreateTelemetryService(Profile* profile) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile);
diff --git a/chrome/browser/safe_browsing/android/services_delegate_android.h b/chrome/browser/safe_browsing/android/services_delegate_android.h
index fafba3c6..709454e 100644
--- a/chrome/browser/safe_browsing/android/services_delegate_android.h
+++ b/chrome/browser/safe_browsing/android/services_delegate_android.h
@@ -44,9 +44,6 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const V4ProtocolConfig& v4_config) override;
   void StopOnIOThread(bool shutdown) override;
-  void OnProfileWillBeDestroyedOnIOThread(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
-      override;
 
   void CreateTelemetryService(Profile* profile) override;
   void RemoveTelemetryService(Profile* profile) override;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index 90868136..432d5016 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -444,7 +444,8 @@
     UMA_HISTOGRAM_ENUMERATION(
         "SBClientPhishing.ClassifierNotReadyReason",
         csd_service_->GetLastModelStatus(
-            IsExtendedReportingEnabled(*profile->GetPrefs())));
+            IsExtendedReportingEnabled(*profile->GetPrefs()) ||
+            IsEnhancedProtectionEnabled(*profile->GetPrefs())));
   }
   if (result != mojom::PhishingDetectorResult::SUCCESS)
     return;
@@ -520,7 +521,8 @@
   // Send ping even if the browser feature extraction failed.
   csd_service_->SendClientReportPhishingRequest(
       request.release(),  // The service takes ownership of the request object.
-      IsExtendedReportingEnabled(*profile->GetPrefs()), callback);
+      IsExtendedReportingEnabled(*profile->GetPrefs()),
+      IsEnhancedProtectionEnabled(*profile->GetPrefs()), callback);
 }
 
 bool ClientSideDetectionHost::DidShowSBInterstitial() const {
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index da8894e..72ac19b 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -112,9 +112,10 @@
   MockClientSideDetectionService() : ClientSideDetectionService(nullptr) {}
   ~MockClientSideDetectionService() override {}
 
-  MOCK_METHOD3(SendClientReportPhishingRequest,
+  MOCK_METHOD4(SendClientReportPhishingRequest,
                void(ClientPhishingRequest*,
                     bool,
+                    bool,
                     const ClientReportPhishingRequestCallback&));
   MOCK_CONST_METHOD1(IsPrivateIPAddress, bool(const std::string&));
   MOCK_METHOD2(GetValidCachedResult, bool(const GURL&, bool*));
@@ -496,8 +497,8 @@
       }));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, _))
-      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<2>(&cb)));
+                  Pointee(PartiallyEqualVerdict(verdict)), _, _, _))
+      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<3>(&cb)));
   PhishingDetectionDone(verdict.SerializeAsString());
   EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
   ASSERT_FALSE(cb.is_null());
@@ -531,8 +532,8 @@
       }));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, _))
-      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<2>(&cb)));
+                  Pointee(PartiallyEqualVerdict(verdict)), _, _, _))
+      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<3>(&cb)));
   PhishingDetectionDone(verdict.SerializeAsString());
   EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
   ASSERT_FALSE(cb.is_null());
@@ -567,8 +568,8 @@
       }));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, _))
-      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<2>(&cb)));
+                  Pointee(PartiallyEqualVerdict(verdict)), _, _, _))
+      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<3>(&cb)));
   PhishingDetectionDone(verdict.SerializeAsString());
   EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
   EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
@@ -621,8 +622,8 @@
       }));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, _))
-      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<2>(&cb)));
+                  Pointee(PartiallyEqualVerdict(verdict)), _, _, _))
+      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<3>(&cb)));
   PhishingDetectionDone(verdict.SerializeAsString());
   EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
   EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
@@ -645,10 +646,9 @@
   verdict.set_client_score(0.8f);
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, _))
-      .WillOnce(DoAll(DeleteArg<0>(),
-                      SaveArg<2>(&cb_other),
-                      QuitUIMessageLoop()));
+                  Pointee(PartiallyEqualVerdict(verdict)), _, _, _))
+      .WillOnce(
+          DoAll(DeleteArg<0>(), SaveArg<3>(&cb_other), QuitUIMessageLoop()));
   std::vector<GURL> redirect_chain;
   redirect_chain.push_back(other_phishing_url);
   SetRedirectChain(redirect_chain);
@@ -716,9 +716,9 @@
   WaitAndCheckPreClassificationChecks();
   SetUnsafeSubResourceForCurrent(true /* expect_unsafe_resource */);
 
-  EXPECT_CALL(*csd_service_,
-              SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, CallbackIsNull()))
+  EXPECT_CALL(*csd_service_, SendClientReportPhishingRequest(
+                                 Pointee(PartiallyEqualVerdict(verdict)), _, _,
+                                 CallbackIsNull()))
       .WillOnce(DoAll(DeleteArg<0>(), QuitUIMessageLoop()));
   std::vector<GURL> redirect_chain;
   redirect_chain.push_back(url);
@@ -754,9 +754,9 @@
   NavigateWithSBHitAndCommit(url);
   WaitAndCheckPreClassificationChecks();
 
-  EXPECT_CALL(*csd_service_,
-              SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, CallbackIsNull()))
+  EXPECT_CALL(*csd_service_, SendClientReportPhishingRequest(
+                                 Pointee(PartiallyEqualVerdict(verdict)), _, _,
+                                 CallbackIsNull()))
       .WillOnce(DoAll(DeleteArg<0>(), QuitUIMessageLoop()));
   std::vector<GURL> redirect_chain;
   redirect_chain.push_back(url);
@@ -810,9 +810,9 @@
   // Even though we have a pending navigation, the DidShowSBInterstitial check
   // should apply to the committed navigation, so we should get a report even
   // though the verdict has is_phishing = false.
-  EXPECT_CALL(*csd_service_,
-              SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, CallbackIsNull()))
+  EXPECT_CALL(*csd_service_, SendClientReportPhishingRequest(
+                                 Pointee(PartiallyEqualVerdict(verdict)), _, _,
+                                 CallbackIsNull()))
       .WillOnce(DoAll(DeleteArg<0>(), QuitUIMessageLoop()));
   std::vector<GURL> redirect_chain;
   redirect_chain.push_back(url);
@@ -1129,9 +1129,9 @@
   const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(10);
   AdvanceTimeTickClock(duration);
 
-  EXPECT_CALL(*csd_service_,
-              SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _, CallbackIsNull()))
+  EXPECT_CALL(*csd_service_, SendClientReportPhishingRequest(
+                                 Pointee(PartiallyEqualVerdict(verdict)), _, _,
+                                 CallbackIsNull()))
       .WillOnce(DoAll(DeleteArg<0>(), QuitUIMessageLoop()));
   std::vector<GURL> redirect_chain;
   redirect_chain.push_back(url);
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index a695382..cd4cdae 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -126,6 +126,7 @@
 void ClientSideDetectionService::SendClientReportPhishingRequest(
     ClientPhishingRequest* verdict,
     bool is_extended_reporting,
+    bool is_enhanced_reporting,
     const ClientReportPhishingRequestCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -133,7 +134,7 @@
       base::BindOnce(
           &ClientSideDetectionService::StartClientReportPhishingRequest,
           weak_factory_.GetWeakPtr(), verdict, is_extended_reporting,
-          callback));
+          is_enhanced_reporting, callback));
 }
 
 bool ClientSideDetectionService::IsPrivateIPAddress(
@@ -182,7 +183,8 @@
   Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext());
   std::string model;
   if (profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
-    if (IsExtendedReportingEnabled(*profile->GetPrefs())) {
+    if (IsExtendedReportingEnabled(*profile->GetPrefs()) ||
+        IsEnhancedProtectionEnabled(*profile->GetPrefs())) {
       DVLOG(2) << "Sending phishing model " << model_loader_extended_->name()
                << " to RenderProcessHost @" << process;
       model = model_loader_extended_->model_str();
@@ -214,6 +216,7 @@
 void ClientSideDetectionService::StartClientReportPhishingRequest(
     ClientPhishingRequest* verdict,
     bool is_extended_reporting,
+    bool is_enhanced_reporting,
     const ClientReportPhishingRequestCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::unique_ptr<ClientPhishingRequest> request(verdict);
@@ -225,10 +228,15 @@
   }
 
   // Fill in metadata about which model we used.
-  if (is_extended_reporting) {
+  if (is_extended_reporting || is_enhanced_reporting) {
     request->set_model_filename(model_loader_extended_->name());
-    request->mutable_population()->set_user_population(
-        ChromeUserPopulation::EXTENDED_REPORTING);
+    if (is_enhanced_reporting) {
+      request->mutable_population()->set_user_population(
+          ChromeUserPopulation::ENHANCED_PROTECTION);
+    } else {
+      request->mutable_population()->set_user_population(
+          ChromeUserPopulation::EXTENDED_REPORTING);
+    }
   } else {
     request->set_model_filename(model_loader_standard_->name());
     request->mutable_population()->set_user_population(
@@ -426,10 +434,9 @@
 }
 
 ModelLoader::ClientModelStatus ClientSideDetectionService::GetLastModelStatus(
-    bool is_extended_reporting) {
-  ModelLoader* model_loader = is_extended_reporting
-                                  ? model_loader_extended_.get()
-                                  : model_loader_standard_.get();
+    bool use_extended_model) {
+  ModelLoader* model_loader = use_extended_model ? model_loader_extended_.get()
+                                                 : model_loader_standard_.get();
   return model_loader->last_client_model_status();
 }
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.h b/chrome/browser/safe_browsing/client_side_detection_service.h
index aca7da72..0339bcb 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.h
+++ b/chrome/browser/safe_browsing/client_side_detection_service.h
@@ -86,15 +86,17 @@
   // The URL scheme of the |url()| in the request should be HTTP.  This method
   // takes ownership of the |verdict| as well as the |callback| and calls the
   // the callback once the result has come back from the server or if an error
-  // occurs during the fetch.  |is_extended_reporting| should be set based on
-  // the active profile setting. If the service is disabled or an error occurs
-  // the phishing verdict will always be false.  The callback is always called
-  // after SendClientReportPhishingRequest() returns and on the same thread as
+  // occurs during the fetch.  |is_extended_reporting| and
+  // |is_enhanced_protection| should be set based on the active profile setting.
+  // If the service is disabled or an error occurs the phishing verdict will
+  // always be false.  The callback is always called after
+  // SendClientReportPhishingRequest() returns and on the same thread as
   // SendClientReportPhishingRequest() was called.  You may set |callback| to
   // NULL if you don't care about the server verdict.
   virtual void SendClientReportPhishingRequest(
       ClientPhishingRequest* verdict,
       bool is_extended_reporting,
+      bool is_enhanced_protection,
       const ClientReportPhishingRequestCallback& callback);
 
   // Returns true if the given IP address string falls within a private
@@ -124,7 +126,7 @@
 
   // Get the model status for the given client-side model (extended reporting or
   // regular).
-  ModelLoader::ClientModelStatus GetLastModelStatus(bool is_extended_reporting);
+  ModelLoader::ClientModelStatus GetLastModelStatus(bool use_extended_model);
 
  protected:
   // Use Create() method to create an instance of this object.
@@ -157,6 +159,7 @@
   void StartClientReportPhishingRequest(
       ClientPhishingRequest* verdict,
       bool is_extended_reporting,
+      bool is_enhanced_protection,
       const ClientReportPhishingRequestCallback& callback);
 
   // Called by OnURLFetchComplete to handle the server response from
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
index 9238110c..a2da3424 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -89,7 +89,7 @@
     request->set_is_phishing(true);  // client thinks the URL is phishing.
     base::RunLoop run_loop;
     csd_service_->SendClientReportPhishingRequest(
-        request, false,
+        request, false, false,
         base::Bind(&ClientSideDetectionServiceTest::SendRequestDone,
                    base::Unretained(this), run_loop.QuitWhenIdleClosure()));
     phishing_url_ = phishing_url;
diff --git a/chrome/browser/safe_browsing/download_protection/download_url_sb_client.cc b/chrome/browser/safe_browsing/download_protection/download_url_sb_client.cc
index 7ec073f7..5ce1168 100644
--- a/chrome/browser/safe_browsing/download_protection/download_url_sb_client.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_url_sb_client.cc
@@ -45,6 +45,8 @@
   extended_reporting_level_ =
       profile ? GetExtendedReportingLevel(*profile->GetPrefs())
               : SBER_LEVEL_OFF;
+  is_enhanced_protection_ =
+      profile ? IsEnhancedProtectionEnabled(*profile->GetPrefs()) : false;
 }
 
 // Implements DownloadItem::Observer.
@@ -124,6 +126,7 @@
   hit_report.threat_source = database_manager_->GetThreatSource();
   hit_report.post_data = post_data;
   hit_report.extended_reporting_level = extended_reporting_level_;
+  hit_report.is_enhanced_protection = is_enhanced_protection_;
   hit_report.is_metrics_reporting_active =
       ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
 
diff --git a/chrome/browser/safe_browsing/download_protection/download_url_sb_client.h b/chrome/browser/safe_browsing/download_protection/download_url_sb_client.h
index 60fd5c9..ee34004 100644
--- a/chrome/browser/safe_browsing/download_protection/download_url_sb_client.h
+++ b/chrome/browser/safe_browsing/download_protection/download_url_sb_client.h
@@ -79,6 +79,7 @@
   scoped_refptr<SafeBrowsingUIManager> ui_manager_;
   base::TimeTicks start_time_;
   ExtendedReportingLevel extended_reporting_level_;
+  bool is_enhanced_protection_;
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
   ScopedObserver<download::DownloadItem, download::DownloadItem::Observer>
       download_item_observer_;
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
index a3431e9..ca3d285f 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -305,7 +305,8 @@
     return false;
   if (!profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled))
     return false;
-  return IsExtendedReportingEnabled(*profile->GetPrefs());
+  return IsExtendedReportingEnabled(*profile->GetPrefs()) ||
+         IsEnhancedProtectionEnabled(*profile->GetPrefs());
 }
 
 IncidentReportingService::IncidentReportingService(
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
index 9384340f..cd7bf4bc 100644
--- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
@@ -514,7 +514,8 @@
 size_t SafeBrowsingNavigationObserverManager::CountOfRecentNavigationsToAppend(
     const Profile& profile,
     AttributionResult result) {
-  if (!IsExtendedReportingEnabled(*profile.GetPrefs()) ||
+  if ((!IsExtendedReportingEnabled(*profile.GetPrefs()) &&
+       !IsEnhancedProtectionEnabled(*profile.GetPrefs())) ||
       profile.IsOffTheRecord() || result == SUCCESS_LANDING_REFERRER) {
     return 0u;
   }
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index 52b2482..560f32b 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -381,25 +381,6 @@
   services_delegate_->RemovePasswordProtectionService(profile);
   services_delegate_->RemoveTelemetryService(profile);
   services_delegate_->RemoveBinaryUploadService(profile);
-
-  base::PostTask(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(
-          &SafeBrowsingService::OnProfileWillBeDestroyedOnIOThread, this,
-          std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>(
-              GetURLLoaderFactory())));
-}
-
-void SafeBrowsingService::OnProfileWillBeDestroyedOnIOThread(
-    std::unique_ptr<network::PendingSharedURLLoaderFactory>
-        url_loader_factory) {
-  // If safe browsing is already turned off, there is no work to do on IO
-  // thread.
-  if (!enabled_) {
-    return;
-  }
-  services_delegate_->OnProfileWillBeDestroyedOnIOThread(
-      network::SharedURLLoaderFactory::Create(std::move(url_loader_factory)));
 }
 
 void SafeBrowsingService::CreateServicesForProfile(Profile* profile) {
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index 1f05aace..fb9d0a8 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -230,11 +230,6 @@
   // permanently and cannot be restarted.
   void StopOnIOThread(bool shutdown);
 
-  // Called on the IO thread when any active profile is destroyed.
-  void OnProfileWillBeDestroyedOnIOThread(
-      std::unique_ptr<network::PendingSharedURLLoaderFactory>
-          url_loader_factory);
-
   // Start up SafeBrowsing objects. This can be called at browser start, or when
   // the user checks the "Enable SafeBrowsing" option in the Advanced options
   // UI.
diff --git a/chrome/browser/safe_browsing/services_delegate.h b/chrome/browser/safe_browsing/services_delegate.h
index 8213ecf..7a4ab3e1 100644
--- a/chrome/browser/safe_browsing/services_delegate.h
+++ b/chrome/browser/safe_browsing/services_delegate.h
@@ -121,8 +121,6 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const V4ProtocolConfig& v4_config) = 0;
   virtual void StopOnIOThread(bool shutdown) = 0;
-  virtual void OnProfileWillBeDestroyedOnIOThread(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) = 0;
 
   void CreatePasswordProtectionService(Profile* profile);
   void RemovePasswordProtectionService(Profile* profile);
diff --git a/chrome/browser/safe_browsing/services_delegate_desktop.cc b/chrome/browser/safe_browsing/services_delegate_desktop.cc
index 97df405..dbf0715 100644
--- a/chrome/browser/safe_browsing/services_delegate_desktop.cc
+++ b/chrome/browser/safe_browsing/services_delegate_desktop.cc
@@ -204,11 +204,6 @@
   database_manager_->StopOnIOThread(shutdown);
 }
 
-void ServicesDelegateDesktop::OnProfileWillBeDestroyedOnIOThread(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
-  database_manager_->OnProfileWillBeDestroyedOnIOThread(url_loader_factory);
-}
-
 void ServicesDelegateDesktop::CreateBinaryUploadService(Profile* profile) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile);
diff --git a/chrome/browser/safe_browsing/services_delegate_desktop.h b/chrome/browser/safe_browsing/services_delegate_desktop.h
index 5438c463..5bed763a 100644
--- a/chrome/browser/safe_browsing/services_delegate_desktop.h
+++ b/chrome/browser/safe_browsing/services_delegate_desktop.h
@@ -51,9 +51,6 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const V4ProtocolConfig& v4_config) override;
   void StopOnIOThread(bool shutdown) override;
-  void OnProfileWillBeDestroyedOnIOThread(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
-      override;
 
   // Reports the current extended reporting level. Note that this is an
   // estimation and may not always be correct. It is possible that the
diff --git a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
index 16bc286..dbdb39cf 100644
--- a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
+++ b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
@@ -154,9 +154,12 @@
     return false;
   }
 
-  if (!IsExtendedReportingEnabled(*GetPrefs())) {
+  bool no_ping_allowed = !IsExtendedReportingEnabled(*GetPrefs()) &&
+                         !IsEnhancedProtectionEnabled(*GetPrefs());
+
+  if (no_ping_allowed) {
     RecordApkDownloadTelemetryOutcome(
-        ApkDownloadTelemetryOutcome::NOT_SENT_EXTENDED_REPORTING_DISABLED);
+        ApkDownloadTelemetryOutcome::NOT_SENT_UNCONSENTED);
     return false;
   }
 
diff --git a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.h b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.h
index ac4659786..c7dc26e 100644
--- a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.h
+++ b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.h
@@ -35,6 +35,7 @@
   // No ping sent because the user is in Incognito mode.
   NOT_SENT_INCOGNITO = 2,
   // No ping sent because the user hasn't enabled extended reporting.
+  // Deprecated for NOT_SENT_UNCONSENTED.
   NOT_SENT_EXTENDED_REPORTING_DISABLED = 3,
   // Download was cancelled.
   NOT_SENT_DOWNLOAD_CANCELLED = 4,
@@ -44,8 +45,10 @@
   NOT_SENT_FEATURE_NOT_ENABLED = 6,
   // Download completed. Ping sent.
   SENT = 7,
-
-  kMaxValue = SENT
+  // No ping sent because the user hasn't enabled enhanced protection and
+  // extended reporting.
+  NOT_SENT_UNCONSENTED = 8,
+  kMaxValue = NOT_SENT_UNCONSENTED
 };
 
 // This class is used to send telemetry information to Safe Browsing for
diff --git a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc
index ffbfc09..4e4113c 100644
--- a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc
+++ b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc
@@ -165,10 +165,12 @@
   ResetProfile();
 }
 
-TEST_F(AndroidTelemetryServiceTest, CantSendPing_SBERDisabled) {
+TEST_F(AndroidTelemetryServiceTest,
+       CantSendPing_SBEREnhancedProtectionDisabled) {
   // Disable Scout Reporting.
   profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingScoutReportingEnabled,
                                     false);
+  profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnhanced, false);
 
   // Enable Safe Browsing.
   profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled, true);
@@ -182,7 +184,7 @@
   get_histograms()->ExpectTotalCount(kApkDownloadTelemetryOutcomeMetric, 1);
   get_histograms()->ExpectBucketCount(
       kApkDownloadTelemetryOutcomeMetric,
-      ApkDownloadTelemetryOutcome::NOT_SENT_EXTENDED_REPORTING_DISABLED, 1);
+      ApkDownloadTelemetryOutcome::NOT_SENT_UNCONSENTED, 1);
 }
 
 TEST_F(AndroidTelemetryServiceTest, CanSendPing_AllConditionsMet) {
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc
index 7adc48d..746025c 100644
--- a/chrome/browser/safe_browsing/ui_manager.cc
+++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -94,6 +94,8 @@
   hit_report.extended_reporting_level =
       profile ? GetExtendedReportingLevel(*profile->GetPrefs())
               : SBER_LEVEL_OFF;
+  hit_report.is_enhanced_protection =
+      IsEnhancedProtectionEnabled(*profile->GetPrefs());
   hit_report.is_metrics_reporting_active =
       ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
 
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
index 54af434..9cb8304 100644
--- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
+++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
@@ -53,10 +53,8 @@
     content::DedicatedWorkerId dedicated_worker_id,
     int worker_process_id,
     content::GlobalFrameRoutingId ancestor_render_frame_host_id) {
-  // TODO(https://crbug.com/1047787): Make use of the worker's URL when it is
-  //                                  available.
   CreateWorkerTask(dedicated_worker_id, Task::Type::DEDICATED_WORKER,
-                   worker_process_id, GURL(), &dedicated_worker_tasks_);
+                   worker_process_id, &dedicated_worker_tasks_);
 }
 
 void PerProfileWorkerTaskTracker::OnBeforeWorkerTerminated(
@@ -65,14 +63,18 @@
   DeleteWorkerTask(dedicated_worker_id, &dedicated_worker_tasks_);
 }
 
+void PerProfileWorkerTaskTracker::OnFinalResponseURLDetermined(
+    content::DedicatedWorkerId dedicated_worker_id,
+    const GURL& url) {
+  SetWorkerTaskScriptUrl(dedicated_worker_id, url, &dedicated_worker_tasks_);
+}
+
 void PerProfileWorkerTaskTracker::OnWorkerStarted(
     content::SharedWorkerId shared_worker_id,
     int worker_process_id,
     const base::UnguessableToken& dev_tools_token) {
-  // TODO(https://crbug.com/1047787): Make use of the worker's URL when it is
-  //                                  available.
   CreateWorkerTask(shared_worker_id, Task::Type::SHARED_WORKER,
-                   worker_process_id, GURL(), &shared_worker_tasks_);
+                   worker_process_id, &shared_worker_tasks_);
 }
 
 void PerProfileWorkerTaskTracker::OnBeforeWorkerTerminated(
@@ -80,12 +82,19 @@
   DeleteWorkerTask(shared_worker_id, &shared_worker_tasks_);
 }
 
+void PerProfileWorkerTaskTracker::OnFinalResponseURLDetermined(
+    content::SharedWorkerId shared_worker_id,
+    const GURL& url) {
+  SetWorkerTaskScriptUrl(shared_worker_id, url, &shared_worker_tasks_);
+}
+
 void PerProfileWorkerTaskTracker::OnVersionStartedRunning(
     int64_t version_id,
     const content::ServiceWorkerRunningInfo& running_info) {
   CreateWorkerTask(version_id, Task::Type::SERVICE_WORKER,
-                   running_info.render_process_id, running_info.script_url,
-                   &service_worker_tasks_);
+                   running_info.render_process_id, &service_worker_tasks_);
+  SetWorkerTaskScriptUrl(version_id, running_info.script_url,
+                         &service_worker_tasks_);
 }
 
 void PerProfileWorkerTaskTracker::OnVersionStoppedRunning(int64_t version_id) {
@@ -97,14 +106,13 @@
     const WorkerId& worker_id,
     Task::Type task_type,
     int worker_process_id,
-    const GURL& script_url,
     base::flat_map<WorkerId, std::unique_ptr<WorkerTask>>* out_worker_tasks) {
   auto* worker_process_host =
       content::RenderProcessHost::FromID(worker_process_id);
   auto insertion_result = out_worker_tasks->emplace(
       worker_id,
       std::make_unique<WorkerTask>(worker_process_host->GetProcess().Handle(),
-                                   script_url, task_type, worker_process_id));
+                                   task_type, worker_process_id));
   DCHECK(insertion_result.second);
   worker_task_provider_->OnWorkerTaskAdded(
       insertion_result.first->second.get());
@@ -120,4 +128,14 @@
   out_worker_tasks->erase(it);
 }
 
+template <typename WorkerId>
+void PerProfileWorkerTaskTracker::SetWorkerTaskScriptUrl(
+    const WorkerId& worker_id,
+    const GURL& script_url,
+    base::flat_map<WorkerId, std::unique_ptr<WorkerTask>>* out_worker_tasks) {
+  auto it = out_worker_tasks->find(worker_id);
+  DCHECK(it != out_worker_tasks->end());
+  it->second->SetScriptUrl(script_url);
+}
+
 }  // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
index a7b5979..01285d3 100644
--- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
+++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
@@ -47,6 +47,9 @@
   void OnBeforeWorkerTerminated(
       content::DedicatedWorkerId dedicated_worker_id,
       content::GlobalFrameRoutingId ancestor_render_frame_host_id) override;
+  void OnFinalResponseURLDetermined(
+      content::DedicatedWorkerId dedicated_worker_id,
+      const GURL& url) override;
 
   // content::SharedWorkerService::Observer:
   void OnWorkerStarted(content::SharedWorkerId shared_worker_id,
@@ -54,6 +57,8 @@
                        const base::UnguessableToken& dev_tools_token) override;
   void OnBeforeWorkerTerminated(
       content::SharedWorkerId shared_worker_id) override;
+  void OnFinalResponseURLDetermined(content::SharedWorkerId shared_worker_id,
+                                    const GURL& url) override;
   void OnClientAdded(
       content::SharedWorkerId shared_worker_id,
       content::GlobalFrameRoutingId render_frame_host_id) override {}
@@ -78,16 +83,28 @@
       const WorkerId& worker_id,
       Task::Type task_type,
       int worker_process_id,
-      const GURL& script_url,
       base::flat_map<WorkerId, std::unique_ptr<WorkerTask>>* out_worker_tasks);
 
   // Deletes an existing WorkerTask from |out_worker_tasks| and notifies
   // |worker_task_provider_| about the deletion of the task.
+  //
+  // Note that this function is templated because each worker type uses a
+  // different type as its ID.
   template <typename WorkerId>
   void DeleteWorkerTask(
       const WorkerId& worker_id,
       base::flat_map<WorkerId, std::unique_ptr<WorkerTask>>* out_worker_tasks);
 
+  // Sets the script URL of an existing WorkerTask.
+  //
+  // Note that this function is templated because each worker type uses a
+  // different type as its ID.
+  template <typename WorkerId>
+  void SetWorkerTaskScriptUrl(
+      const WorkerId& worker_id,
+      const GURL& script_url,
+      base::flat_map<WorkerId, std::unique_ptr<WorkerTask>>* out_worker_tasks);
+
   // The provider that gets notified when a WorkerTask is created/deleted.
   WorkerTaskProvider* const worker_task_provider_;  // Owner.
 
diff --git a/chrome/browser/task_manager/providers/worker_task.cc b/chrome/browser/task_manager/providers/worker_task.cc
index d0555e8..82f2fde 100644
--- a/chrome/browser/task_manager/providers/worker_task.cc
+++ b/chrome/browser/task_manager/providers/worker_task.cc
@@ -4,12 +4,17 @@
 
 #include "chrome/browser/task_manager/providers/worker_task.h"
 
+#include <string>
+
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 namespace task_manager {
 
+namespace {
+
 int GetTaskTitlePrefixMessageId(Task::Type task_type) {
   switch (task_type) {
     case Task::Type::DEDICATED_WORKER:
@@ -24,14 +29,19 @@
   }
 }
 
+base::string16 GetTaskTitle(const GURL& script_url, Task::Type task_type) {
+  return l10n_util::GetStringFUTF16(GetTaskTitlePrefixMessageId(task_type),
+                                    base::UTF8ToUTF16(script_url.spec()));
+}
+
+}  // namespace
+
 WorkerTask::WorkerTask(base::ProcessHandle handle,
-                       const GURL& script_url,
                        Task::Type task_type,
                        int render_process_id)
-    : Task(l10n_util::GetStringFUTF16(GetTaskTitlePrefixMessageId(task_type),
-                                      base::UTF8ToUTF16(script_url.spec())),
-           script_url.spec(),
-           nullptr /* icon */,
+    : Task(GetTaskTitle(/*script_url=*/GURL(), task_type),
+           /*rappor_sample=*/std::string(),
+           /*icon=*/nullptr,
            handle),
       task_type_(task_type),
       render_process_id_(render_process_id) {}
@@ -46,4 +56,9 @@
   return render_process_id_;
 }
 
+void WorkerTask::SetScriptUrl(const GURL& script_url) {
+  set_title(GetTaskTitle(script_url, task_type_));
+  set_rappor_sample_name(script_url.spec());
+}
+
 }  // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/worker_task.h b/chrome/browser/task_manager/providers/worker_task.h
index 396abb44..cce950a6 100644
--- a/chrome/browser/task_manager/providers/worker_task.h
+++ b/chrome/browser/task_manager/providers/worker_task.h
@@ -6,7 +6,8 @@
 #define CHROME_BROWSER_TASK_MANAGER_PROVIDERS_WORKER_TASK_H_
 
 #include "chrome/browser/task_manager/providers/task.h"
-#include "url/gurl.h"
+
+class GURL;
 
 namespace task_manager {
 
@@ -17,7 +18,6 @@
 class WorkerTask : public Task {
  public:
   WorkerTask(base::ProcessHandle handle,
-             const GURL& script_url,
              Task::Type task_type,
              int render_process_id);
   ~WorkerTask() override;
@@ -30,6 +30,9 @@
   Task::Type GetType() const override;
   int GetChildProcessUniqueID() const override;
 
+  // Invoked when the final response URL of the worker script is determined.
+  void SetScriptUrl(const GURL& script_url);
+
  private:
   // The type of this worker task. Can be one of DEDICATED_WORKER, SHARED_WORKER
   // or SERVICE_WORKER.
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 4b3ed34..814b0805 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -69,7 +69,7 @@
 // change default theme assets, if you need themes to recreate their generated
 // images (which are cached), or if you changed how missing values are
 // generated.
-const int kThemePackVersion = 73;
+const int kThemePackVersion = 74;
 
 // IDs that are in the DataPack won't clash with the positive integer
 // uint16_t. kHeaderID should always have the maximum value because we want the
@@ -1054,9 +1054,9 @@
 void BrowserThemePack::AdjustThemePack() {
   CropImages(&images_);
 
-  // Set toolbar related elements' colors (e.g. status bubble, info bar,
-  // download shelf) to toolbar color.
-  SetToolbarRelatedColors();
+  // Set frame and toolbar related elements' colors (e.g. status bubble,
+  // info bar, download shelf) to frame or toolbar color.
+  SetFrameAndToolbarRelatedColors();
 
   // Create toolbar image, and generate toolbar color from image where relevant.
   // This must be done after reading colors from JSON (so they can be used for
@@ -1470,15 +1470,16 @@
   }
 }
 
-void BrowserThemePack::SetToolbarRelatedColors() {
-  // Propagate the user-specified Toolbar Color to similar elements (for
-  // backwards-compatibility with themes written before this toolbar processing
-  // was introduced).
+void BrowserThemePack::SetFrameAndToolbarRelatedColors() {
+  // Propagate the user-specified Frame and Toolbar Colors to similar elements.
+  SkColor frame_color;
+  if (GetColor(TP::COLOR_FRAME, &frame_color))
+    SetColor(TP::COLOR_STATUS_BUBBLE, frame_color);
+
   SkColor toolbar_color;
   if (GetColor(TP::COLOR_TOOLBAR, &toolbar_color)) {
     SetColor(TP::COLOR_INFOBAR, toolbar_color);
     SetColor(TP::COLOR_DOWNLOAD_SHELF, toolbar_color);
-    SetColor(TP::COLOR_STATUS_BUBBLE, toolbar_color);
   }
   SkColor toolbar_button_icon_color;
   if (GetColor(TP::COLOR_TOOLBAR_BUTTON_ICON, &toolbar_button_icon_color)) {
diff --git a/chrome/browser/themes/browser_theme_pack.h b/chrome/browser/themes/browser_theme_pack.h
index def58c1..6dfc2bf 100644
--- a/chrome/browser/themes/browser_theme_pack.h
+++ b/chrome/browser/themes/browser_theme_pack.h
@@ -214,9 +214,9 @@
   // can be of any size. Source and destination is |images|.
   void CropImages(ImageCache* images) const;
 
-  // Set toolbar related elements' colors (e.g. status bubble, info bar,
-  // download shelf) to toolbar color.
-  void SetToolbarRelatedColors();
+  // Set frame and toolbar related elements' colors (e.g. status bubble,
+  // info bar, download shelf) to frame or toolbar colors.
+  void SetFrameAndToolbarRelatedColors();
 
   // Creates a composited toolbar image. Source and destination is |images|.
   // Also sets toolbar color corresponding to this image.
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index c36e66b..07bb57d 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -939,47 +939,44 @@
   }
 }
 
-// Ensure that a specified 'toolbar' color is propagated to other 'bar' and
-// 'shelf' colors (before a new color is computed from the toolbar image).
-TEST_F(BrowserThemePackTest, TestToolbarColorPropagation) {
-  scoped_refptr<BrowserThemePack> pack(
-      new BrowserThemePack(CustomThemeSupplier::ThemeType::EXTENSION));
-  BuildTestExtensionTheme("theme_test_toolbar_frame_images_and_colors",
-                          pack.get());
-
-  SkColor infobar_color;
-  SkColor download_shelf_color;
-  SkColor status_bubble_color;
-
-  EXPECT_TRUE(pack->GetColor(TP::COLOR_INFOBAR, &infobar_color));
-  EXPECT_TRUE(pack->GetColor(TP::COLOR_DOWNLOAD_SHELF, &download_shelf_color));
-  EXPECT_TRUE(pack->GetColor(TP::COLOR_STATUS_BUBBLE, &status_bubble_color));
-
-  constexpr SkColor kExpectedColor = SkColorSetRGB(0, 255, 0);
-  EXPECT_EQ(infobar_color, kExpectedColor);
-  EXPECT_EQ(infobar_color, download_shelf_color);
-  EXPECT_EQ(infobar_color, status_bubble_color);
-}
-
-// Ensure that a specified 'toolbar' color is propagated to other 'bar' and
-// 'shelf' colors (before a new color is computed from the toolbar image).
-TEST_F(BrowserThemePackTest, TestToolbarColorPropagationNoImage) {
+// Ensure that specified 'frame' and 'toolbar' colors are propagated to other
+// 'bar' and 'shelf' colors.
+TEST_F(BrowserThemePackTest, TestFrameAndToolbarColorPropagation) {
   scoped_refptr<BrowserThemePack> pack(
       new BrowserThemePack(CustomThemeSupplier::ThemeType::EXTENSION));
   BuildTestExtensionTheme("theme_test_toolbar_color_no_image", pack.get());
 
+  // Frame colors.
+  SkColor status_bubble_color;
+
+  EXPECT_TRUE(pack->GetColor(TP::COLOR_STATUS_BUBBLE, &status_bubble_color));
+
+  constexpr SkColor kExpectedFrameColor = SkColorSetRGB(255, 0, 255);
+  EXPECT_EQ(status_bubble_color, kExpectedFrameColor);
+
+  // Toolbar colors.
   SkColor infobar_color;
   SkColor download_shelf_color;
-  SkColor status_bubble_color;
 
   EXPECT_TRUE(pack->GetColor(TP::COLOR_INFOBAR, &infobar_color));
   EXPECT_TRUE(pack->GetColor(TP::COLOR_DOWNLOAD_SHELF, &download_shelf_color));
-  EXPECT_TRUE(pack->GetColor(TP::COLOR_STATUS_BUBBLE, &status_bubble_color));
 
-  constexpr SkColor kExpectedColor = SkColorSetRGB(0, 255, 0);
-  EXPECT_EQ(infobar_color, kExpectedColor);
-  EXPECT_EQ(infobar_color, download_shelf_color);
-  EXPECT_EQ(infobar_color, status_bubble_color);
+  constexpr SkColor kExpectedToolbarColor = SkColorSetRGB(0, 255, 0);
+  EXPECT_EQ(infobar_color, kExpectedToolbarColor);
+  EXPECT_EQ(download_shelf_color, kExpectedToolbarColor);
+
+  // Toolbar button icon colors.
+  SkColor toolbar_button_icon_hovered_color;
+  SkColor toolbar_button_icon_pressed_color;
+
+  EXPECT_TRUE(pack->GetColor(TP::COLOR_TOOLBAR_BUTTON_ICON_HOVERED,
+                             &toolbar_button_icon_hovered_color));
+  EXPECT_TRUE(pack->GetColor(TP::COLOR_TOOLBAR_BUTTON_ICON_PRESSED,
+                             &toolbar_button_icon_pressed_color));
+
+  constexpr SkColor kExpectedToolbarButtonIconColor = SkColorSetRGB(0, 0, 255);
+  EXPECT_EQ(toolbar_button_icon_hovered_color, kExpectedToolbarButtonIconColor);
+  EXPECT_EQ(toolbar_button_icon_pressed_color, kExpectedToolbarButtonIconColor);
 }
 
 // Ensure that, given an explicit toolbar color and a toolbar image, the output
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 6abcd12c4..84464a5 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -55,6 +55,7 @@
     case ThemeProperties::COLOR_FRAME:
     case ThemeProperties::COLOR_BACKGROUND_TAB:
     case ThemeProperties::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE:
+    case ThemeProperties::COLOR_STATUS_BUBBLE:
       return SkColorSetRGB(0xDE, 0xE1, 0xE6);
     case ThemeProperties::COLOR_FRAME_INACTIVE:
     case ThemeProperties::COLOR_BACKGROUND_TAB_INACTIVE:
@@ -66,7 +67,6 @@
     case ThemeProperties::COLOR_DOWNLOAD_SHELF:
     case ThemeProperties::COLOR_INFOBAR:
     case ThemeProperties::COLOR_TOOLBAR:
-    case ThemeProperties::COLOR_STATUS_BUBBLE:
       return SK_ColorWHITE;
     case ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND:
       return gfx::kGoogleGrey300;
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
index ac07067..f2c88b0 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -418,9 +418,10 @@
 
   // Launching non-ready ARC app creates item on shelf and spinning animation.
   if (is_pinned()) {
-    EXPECT_EQ(ash::SHELF_ACTION_NEW_WINDOW_CREATED,
-              SelectShelfItem(shelf_id, ui::ET_MOUSE_PRESSED,
-                              display::kInvalidDisplayId));
+    EXPECT_EQ(
+        ash::SHELF_ACTION_NEW_WINDOW_CREATED,
+        SelectShelfItem(shelf_id, ui::ET_MOUSE_PRESSED,
+                        display::kInvalidDisplayId, ash::LAUNCH_FROM_SHELF));
   } else {
     arc::LaunchApp(profile(), app_id, ui::EF_LEFT_MOUSE_BUTTON,
                    arc::UserInteractionType::NOT_USER_INITIATED);
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 68868ba..90e4972 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -79,6 +79,7 @@
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
+#include "chrome/services/app_service/public/mojom/types.mojom.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/arc_prefs.h"
@@ -139,6 +140,19 @@
   return registry->GetInstalledExtension(extension_id);
 }
 
+apps::mojom::LaunchSource ConvertLaunchSource(ash::ShelfLaunchSource source) {
+  switch (source) {
+    case ash::LAUNCH_FROM_UNKNOWN:
+      return apps::mojom::LaunchSource::kUnknown;
+    case ash::LAUNCH_FROM_APP_LIST:
+      return apps::mojom::LaunchSource::kFromAppListGrid;
+    case ash::LAUNCH_FROM_APP_LIST_SEARCH:
+      return apps::mojom::LaunchSource::kFromAppListQuery;
+    case ash::LAUNCH_FROM_SHELF:
+      return apps::mojom::LaunchSource::kFromShelf;
+  }
+}
+
 }  // namespace
 
 // A class to get events from ChromeOS when a user gets changed or added.
@@ -481,8 +495,7 @@
   apps::AppServiceProxy* proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile_);
   DCHECK(proxy);
-  proxy->Launch(app_id, event_flags, apps::mojom::LaunchSource::kFromShelf,
-                display_id);
+  proxy->Launch(app_id, event_flags, ConvertLaunchSource(source), display_id);
 }
 
 void ChromeLauncherController::ActivateApp(const std::string& app_id,
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.cc b/chrome/browser/ui/extensions/extension_action_view_controller.cc
index cc317bf..d522564 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller.cc
+++ b/chrome/browser/ui/extensions/extension_action_view_controller.cc
@@ -219,9 +219,19 @@
   return context_menu_model_.get();
 }
 
+void ExtensionActionViewController::OnContextMenuShown() {
+  extensions_container_->OnContextMenuShown(this);
+}
+
 void ExtensionActionViewController::OnContextMenuClosed() {
-  if (extensions_container_->GetPoppedOutAction() == this && !IsShowingPopup())
+  if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
+    extensions_container_->OnContextMenuClosed(this);
+    return;
+  }
+  if (extensions_container_->GetPoppedOutAction() == this &&
+      !view_delegate_->IsMenuRunning()) {
     extensions_container_->UndoPopOut();
+  }
 }
 
 bool ExtensionActionViewController::ExecuteAction(bool by_user) {
@@ -439,7 +449,8 @@
   popup_host_ = nullptr;
   extensions_container_->SetPopupOwner(nullptr);
   if (extensions_container_->GetPoppedOutAction() == this &&
-      !view_delegate_->IsMenuRunning()) {
+      (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu) ||
+       !view_delegate_->IsMenuRunning())) {
     extensions_container_->UndoPopOut();
   }
   view_delegate_->OnPopupClosed();
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.h b/chrome/browser/ui/extensions/extension_action_view_controller.h
index 1750607..cc60073 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller.h
+++ b/chrome/browser/ui/extensions/extension_action_view_controller.h
@@ -68,6 +68,7 @@
   void HidePopup() override;
   gfx::NativeView GetPopupNativeView() override;
   ui::MenuModel* GetContextMenu() override;
+  void OnContextMenuShown() override;
   void OnContextMenuClosed() override;
   bool ExecuteAction(bool by_user) override;
   void UpdateState() override;
diff --git a/chrome/browser/ui/extensions/extensions_container.h b/chrome/browser/ui/extensions/extensions_container.h
index 4a65646..8d80d9f 100644
--- a/chrome/browser/ui/extensions/extensions_container.h
+++ b/chrome/browser/ui/extensions/extensions_container.h
@@ -24,6 +24,14 @@
   // that relate to more than one extension.
   virtual ToolbarActionViewController* GetPoppedOutAction() const = 0;
 
+  // Called when a context menu is shown so the container can perform any
+  // necessary setup.
+  virtual void OnContextMenuShown(ToolbarActionViewController* extension) {}
+
+  // Called when a context menu is closed so the container can perform any
+  // necessary cleanup.
+  virtual void OnContextMenuClosed(ToolbarActionViewController* extension) {}
+
   // Returns true if the given |action| is visible on the toolbar.
   virtual bool IsActionVisibleOnToolbar(
       const ToolbarActionViewController* action) const = 0;
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 990b7f6a..57cb491 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -329,10 +329,7 @@
       embedded_test_server()->GetURL("app.com", "/click_modifier/href.html");
   ui_test_utils::UrlLoadObserver url_observer(
       app_url, content::NotificationService::AllSources());
-  extensions::TestExtensionDir test_app_dir;
-  test_app_dir.WriteManifest(
-      base::StringPrintf(kAppDotComManifest, app_url.spec().c_str()));
-  SetupApp(test_app_dir.UnpackedPath());
+  SetupAppWithURL(app_url);
   // Wait for the URL to load so that we can click on the page.
   url_observer.Wait();
 
@@ -584,10 +581,7 @@
 
   // Set up an app which covers app.com URLs.
   GURL app_url = embedded_test_server()->GetURL("app.com", "/title1.html");
-  extensions::TestExtensionDir test_app_dir;
-  test_app_dir.WriteManifest(
-      base::StringPrintf(kAppDotComManifest, app_url.spec().c_str()));
-  SetupApp(test_app_dir.UnpackedPath());
+  SetupAppWithURL(app_url);
 
   // Navigate a regular tab to a page with a subframe.
   GURL url = embedded_test_server()->GetURL("foo.com", "/iframe.html");
@@ -620,10 +614,7 @@
 
   ui_test_utils::UrlLoadObserver url_observer(
       app_url, content::NotificationService::AllSources());
-  extensions::TestExtensionDir test_app_dir;
-  test_app_dir.WriteManifest(
-      base::StringPrintf(kAppDotComManifest, app_url.spec().c_str()));
-  SetupApp(test_app_dir.UnpackedPath());
+  SetupAppWithURL(app_url);
   url_observer.Wait();
 
   web_app::CheckMixedContentLoaded(app_browser_);
diff --git a/chrome/browser/ui/gtk/gtk_util.cc b/chrome/browser/ui/gtk/gtk_util.cc
index 2bd955b..60614bf 100644
--- a/chrome/browser/ui/gtk/gtk_util.cc
+++ b/chrome/browser/ui/gtk/gtk_util.cc
@@ -309,8 +309,10 @@
   enum {
     CSS_TYPE,
     CSS_NAME,
+    CSS_OBJECT_NAME,
     CSS_CLASS,
     CSS_PSEUDOCLASS,
+    CSS_NONE,
   } part_type = CSS_TYPE;
   static const struct {
     const char* name;
@@ -328,7 +330,7 @@
       {"checked", GTK_STATE_FLAG_CHECKED},
   };
   GtkStateFlags state = GTK_STATE_FLAG_NORMAL;
-  base::StringTokenizer t(css_node, ".:#");
+  base::StringTokenizer t(css_node, ".:#()");
   t.set_options(base::StringTokenizer::RETURN_DELIMS);
   while (t.GetNext()) {
     if (t.token_is_delim()) {
@@ -337,9 +339,15 @@
         gtk_widget_path_append_type(path, G_TYPE_NONE);
       }
       switch (*t.token_begin()) {
-        case '#':
+        case '(':
           part_type = CSS_NAME;
           break;
+        case ')':
+          part_type = CSS_NONE;
+          break;
+        case '#':
+          part_type = CSS_OBJECT_NAME;
+          break;
         case '.':
           part_type = CSS_CLASS;
           break;
@@ -355,14 +363,15 @@
           reinterpret_cast<GtkSetObjectName>(dlsym(
               GetGtkSharedLibrary(), "gtk_widget_path_iter_set_object_name"));
       switch (part_type) {
-        case CSS_NAME: {
-          if (GtkVersionCheck(3, 20)) {
-            _gtk_widget_path_iter_set_object_name(path, -1, t.token().c_str());
-          } else {
-            gtk_widget_path_iter_add_class(path, -1, t.token().c_str());
-          }
+        case CSS_NAME:
+          gtk_widget_path_iter_set_name(path, -1, t.token().c_str());
           break;
-        }
+        case CSS_OBJECT_NAME:
+          if (GtkVersionCheck(3, 20))
+            _gtk_widget_path_iter_set_object_name(path, -1, t.token().c_str());
+          else
+            gtk_widget_path_iter_add_class(path, -1, t.token().c_str());
+          break;
         case CSS_TYPE: {
           GType type = g_type_from_name(t.token().c_str());
           DCHECK(type);
@@ -373,10 +382,9 @@
           }
           break;
         }
-        case CSS_CLASS: {
+        case CSS_CLASS:
           gtk_widget_path_iter_add_class(path, -1, t.token().c_str());
           break;
-        }
         case CSS_PSEUDOCLASS: {
           GtkStateFlags state_flag = GTK_STATE_FLAG_NORMAL;
           for (const auto& pseudo_class_entry : pseudo_classes) {
@@ -388,6 +396,8 @@
           state = static_cast<GtkStateFlags>(state | state_flag);
           break;
         }
+        case CSS_NONE:
+          NOTREACHED();
       }
     }
   }
diff --git a/chrome/browser/ui/gtk/native_theme_gtk.cc b/chrome/browser/ui/gtk/native_theme_gtk.cc
index 1c6b321..aa5e9f54 100644
--- a/chrome/browser/ui/gtk/native_theme_gtk.cc
+++ b/chrome/browser/ui/gtk/native_theme_gtk.cc
@@ -126,6 +126,28 @@
       }
       return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem.separator");
 
+    // Dropdown
+    case ui::NativeTheme::kColorId_DropdownBackgroundColor:
+      return GetBgColor(
+          "GtkComboBoxText#combobox GtkWindow#window.background.popup "
+          "GtkTreeMenu#menu(gtk-combobox-popup-menu) GtkMenuItem#menuitem "
+          "GtkCellView#cellview");
+    case ui::NativeTheme::kColorId_DropdownForegroundColor:
+      return GetFgColor(
+          "GtkComboBoxText#combobox GtkWindow#window.background.popup "
+          "GtkTreeMenu#menu(gtk-combobox-popup-menu) GtkMenuItem#menuitem "
+          "GtkCellView#cellview");
+    case ui::NativeTheme::kColorId_DropdownSelectedBackgroundColor:
+      return GetBgColor(
+          "GtkComboBoxText#combobox GtkWindow#window.background.popup "
+          "GtkTreeMenu#menu(gtk-combobox-popup-menu) "
+          "GtkMenuItem#menuitem:hover GtkCellView#cellview");
+    case ui::NativeTheme::kColorId_DropdownSelectedForegroundColor:
+      return GetFgColor(
+          "GtkComboBoxText#combobox GtkWindow#window.background.popup "
+          "GtkTreeMenu#menu(gtk-combobox-popup-menu) "
+          "GtkMenuItem#menuitem:hover GtkCellView#cellview");
+
     // Label
     case ui::NativeTheme::kColorId_LabelEnabledColor:
       return GetFgColor("GtkLabel");
@@ -368,6 +390,14 @@
   g_type_class_unref(g_type_class_ref(gtk_toggle_button_get_type()));
   g_type_class_unref(g_type_class_ref(gtk_tree_view_get_type()));
   g_type_class_unref(g_type_class_ref(gtk_window_get_type()));
+  g_type_class_unref(g_type_class_ref(gtk_combo_box_text_get_type()));
+  g_type_class_unref(g_type_class_ref(gtk_cell_view_get_type()));
+
+  // Initialize the GtkTreeMenu type.  _gtk_tree_menu_get_type() is private, so
+  // we need to initialize it indirectly.
+  ScopedGObject<GtkTreeModel> model{
+      GTK_TREE_MODEL(gtk_tree_store_new(1, G_TYPE_STRING))};
+  ScopedGObject<GtkWidget> combo{gtk_combo_box_new_with_model(model)};
 
   OnThemeChanged(gtk_settings_get_default(), nullptr);
 }
diff --git a/chrome/browser/ui/toolbar/toolbar_action_view_controller.h b/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
index d9c50784..7fd3dd5 100644
--- a/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
+++ b/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
@@ -88,6 +88,10 @@
   // Returns the context menu model, or null if no context menu should be shown.
   virtual ui::MenuModel* GetContextMenu() = 0;
 
+  // Called when a context menu is shown so the controller can perform any
+  // necessary setup.
+  virtual void OnContextMenuShown() {}
+
   // Called when a context menu has closed so the controller can perform any
   // necessary cleanup.
   virtual void OnContextMenuClosed() {}
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
index 5eeb10c..1a43f4de 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
@@ -37,22 +37,22 @@
 
 SkColor AutofillPopupBaseView::GetBackgroundColor() {
   return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_MenuBackgroundColor);
+      ui::NativeTheme::kColorId_DropdownBackgroundColor);
 }
 
 SkColor AutofillPopupBaseView::GetForegroundColor() {
   return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_EnabledMenuItemForegroundColor);
+      ui::NativeTheme::kColorId_DropdownForegroundColor);
 }
 
 SkColor AutofillPopupBaseView::GetSelectedBackgroundColor() {
   return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor);
+      ui::NativeTheme::kColorId_DropdownSelectedBackgroundColor);
 }
 
 SkColor AutofillPopupBaseView::GetSelectedForegroundColor() {
   return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor);
+      ui::NativeTheme::kColorId_DropdownSelectedForegroundColor);
 }
 
 SkColor AutofillPopupBaseView::GetFooterBackgroundColor() {
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents_browsertest.cc b/chrome/browser/ui/views/content_setting_bubble_contents_browsertest.cc
index fe73837..4e59e27 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents_browsertest.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents_browsertest.cc
@@ -13,12 +13,13 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/permissions/permission_request_manager.h"
+#include "components/permissions/test/permission_request_observer.h"
 #include "content/public/test/browser_test_utils.h"
 
 class ContentSettingBubbleContentsBrowserTest : public InProcessBrowserTest {
  public:
   ContentSettingBubbleContentsBrowserTest() = default;
-  ~ContentSettingBubbleContentsBrowserTest() override {}
+  ~ContentSettingBubbleContentsBrowserTest() override = default;
 
  protected:
   GURL GetTestPageUrl(const std::string& name) {
@@ -30,13 +31,6 @@
   content::WebContents* GetWebContents() {
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
-
-  bool ExecuteScript(const std::string& script) {
-    return content::ExecuteScript(GetWebContents(), script);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ContentSettingBubbleContentsBrowserTest);
 };
 
 IN_PROC_BROWSER_TEST_F(ContentSettingBubbleContentsBrowserTest,
@@ -46,11 +40,13 @@
 
   // Navigate to the test page, and have it request and be denied geolocation
   // permissions.
-  ui_test_utils::NavigateToURL(browser(), GetTestPageUrl("geolocation.html"));
+  ASSERT_TRUE(content::NavigateToURL(GetWebContents(),
+                                     GetTestPageUrl("geolocation.html")));
   permissions::PermissionRequestManager::FromWebContents(GetWebContents())
       ->set_auto_response_for_test(
           permissions::PermissionRequestManager::DISMISS);
-  ExecuteScript("geolocate();");
+  ASSERT_TRUE(content::ExecJs(GetWebContents(), "geolocate();"));
+  permissions::PermissionRequestObserver(GetWebContents()).Wait();
 
   // Press the geolocation icon and make sure its content setting bubble shows.
   LocationBarTesting* bar =
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 268aaba..e932c99 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -348,12 +348,6 @@
              model_->GetState() != DownloadItem::CANCELLED) {
     if (!IsShowingDeepScanning())
       TransitionToDeepScanningDialog();
-
-    if (should_open_while_scanning_ &&
-        model_->GetState() == DownloadItem::COMPLETE) {
-      should_open_while_scanning_ = false;
-      model_->OpenDownload();
-    }
   } else {
     TransitionToNormalMode();
   }
@@ -1626,7 +1620,7 @@
 
 void DownloadItemView::OpenDownloadDuringAsyncScanning() {
   model_->CompleteSafeBrowsingScan();
-  should_open_while_scanning_ = true;
+  model_->SetOpenWhenComplete(true);
 }
 
 void DownloadItemView::StyleFilenameInLabel(views::StyledLabel* label) {
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h
index 23f68a7..c7d667fa 100644
--- a/chrome/browser/ui/views/download/download_item_view.h
+++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -439,10 +439,6 @@
   // Deep scanning open now button.
   views::MdTextButton* open_now_button_ = nullptr;
 
-  // Whether the user has selected "open now" on a download pending asynchronous
-  // scanning.
-  bool should_open_while_scanning_ = false;
-
   // Deep scanning modal dialog confirming choice to "open now".
   TabModalConfirmDialog* open_now_modal_dialog_;
 
diff --git a/chrome/browser/ui/views/extensions/extension_context_menu_controller.cc b/chrome/browser/ui/views/extensions/extension_context_menu_controller.cc
index 8ee7ad3..d4c68852 100644
--- a/chrome/browser/ui/views/extensions/extension_context_menu_controller.cc
+++ b/chrome/browser/ui/views/extensions/extension_context_menu_controller.cc
@@ -56,6 +56,7 @@
 
   menu_runner_ = std::make_unique<views::MenuRunner>(menu_, run_types);
 
+  controller_->OnContextMenuShown();
   menu_runner_->RunMenuAt(
       parent,
       static_cast<views::MenuButtonController*>(
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
index 5ca8b36..8cbb1bf 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/common/web_application_info.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -134,22 +135,24 @@
 }
 
 #if defined(OS_CHROMEOS)
-// Test that we don't crash when uninstalling an extension from a bookmark app
+// Test that we don't crash when uninstalling an extension from a web app
 // window in Ash. Context: crbug.com/825554
 IN_PROC_BROWSER_TEST_F(ExtensionUninstallDialogViewBrowserTest,
-                       BookmarkAppWindowAshCrash) {
+                       WebAppWindowAshCrash) {
   scoped_refptr<const extensions::Extension> extension(BuildTestExtension());
   extensions::ExtensionSystem::Get(browser()->profile())
       ->extension_service()
       ->AddExtension(extension.get());
 
-  WebApplicationInfo info;
-  info.app_url = GURL("https://test.com/");
-  const extensions::Extension* bookmark_app =
-      extensions::browsertest_util::InstallBookmarkApp(browser()->profile(),
-                                                       info);
-  Browser* app_browser = extensions::browsertest_util::LaunchAppBrowser(
-      browser()->profile(), bookmark_app);
+  const GURL app_url = GURL("https://test.com/");
+  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  web_app_info->app_url = app_url;
+  web_app_info->scope = app_url;
+  web_app_info->open_as_window = true;
+  web_app::AppId app_id =
+      web_app::InstallWebApp(browser()->profile(), std::move(web_app_info));
+  Browser* app_browser =
+      web_app::LaunchWebAppBrowser(browser()->profile(), app_id);
 
   std::unique_ptr<extensions::ExtensionUninstallDialog> dialog;
   {
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
index ed50f28e..74e1c96 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
@@ -215,6 +215,17 @@
     views::test::WaitForAnimatingLayoutManager(GetExtensionsToolbarContainer());
   }
 
+  void RightClickExtensionInToolbar(ToolbarActionView* extension) {
+    ui::MouseEvent click_down_event(ui::ET_MOUSE_PRESSED, gfx::Point(),
+                                    gfx::Point(), base::TimeTicks(),
+                                    ui::EF_RIGHT_MOUSE_BUTTON, 0);
+    ui::MouseEvent click_up_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
+                                  gfx::Point(), base::TimeTicks(),
+                                  ui::EF_RIGHT_MOUSE_BUTTON, 0);
+    extension->OnMouseEvent(&click_down_event);
+    extension->OnMouseEvent(&click_up_event);
+  }
+
   void ClickExtensionsMenuButton(Browser* browser) {
     ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                                base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0);
@@ -389,6 +400,46 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest,
+                       ContextMenuKeepsExtensionPoppedOut) {
+  LoadTestExtension("extensions/simple_with_popup");
+  ShowUi("");
+  VerifyUi();
+
+  ExtensionsToolbarContainer* const extensions_container =
+      GetExtensionsToolbarContainer();
+
+  EXPECT_EQ(nullptr, extensions_container->GetPoppedOutAction());
+  EXPECT_TRUE(GetVisibleToolbarActionViews().empty());
+
+  TriggerSingleExtensionButton();
+
+  // After triggering an extension with a popup, there should a popped-out
+  // action and show the view.
+  auto visible_icons = GetVisibleToolbarActionViews();
+  EXPECT_NE(nullptr, extensions_container->GetPoppedOutAction());
+  EXPECT_EQ(base::nullopt,
+            extensions_container->GetExtensionWithOpenContextMenuForTesting());
+  ASSERT_EQ(1u, visible_icons.size());
+  EXPECT_EQ(extensions_container->GetPoppedOutAction(),
+            visible_icons[0]->view_controller());
+
+  RightClickExtensionInToolbar(extensions_container->GetViewForId(
+      extensions_container->GetPoppedOutAction()->GetId()));
+  extensions_container->HideActivePopup();
+
+  // Wait for animations to finish.
+  views::test::WaitForAnimatingLayoutManager(extensions_container);
+
+  visible_icons = GetVisibleToolbarActionViews();
+  ASSERT_EQ(1u, visible_icons.size());
+  EXPECT_EQ(nullptr, extensions_container->GetPoppedOutAction());
+  EXPECT_NE(base::nullopt,
+            extensions_container->GetExtensionWithOpenContextMenuForTesting());
+  EXPECT_EQ(extensions_container->GetExtensionWithOpenContextMenuForTesting(),
+            visible_icons[0]->view_controller()->GetId());
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest,
                        RemoveExtensionShowingPopup) {
   LoadTestExtension("extensions/simple_with_popup");
   ShowUi("");
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
index 584e5dd..3cef4dc7 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
@@ -137,6 +137,11 @@
   if (popped_out_action_ && popped_out_action_->GetId() == extension_id)
     return true;
 
+  if (extension_with_open_context_menu_id_.has_value() &&
+      extension_with_open_context_menu_id_.value() == extension_id) {
+    return true;
+  }
+
   for (const auto& anchored_widget : anchored_widgets_) {
     if (anchored_widget.extension_id == extension_id)
       return true;
@@ -227,6 +232,21 @@
   return popped_out_action_;
 }
 
+void ExtensionsToolbarContainer::OnContextMenuShown(
+    ToolbarActionViewController* extension) {
+  extension_with_open_context_menu_id_ = extension->GetId();
+  UpdateIconVisibility(extension_with_open_context_menu_id_.value());
+}
+
+void ExtensionsToolbarContainer::OnContextMenuClosed(
+    ToolbarActionViewController* extension) {
+  DCHECK(extension_with_open_context_menu_id_.has_value());
+  base::Optional<extensions::ExtensionId> const
+      extension_with_open_context_menu = extension_with_open_context_menu_id_;
+  extension_with_open_context_menu_id_.reset();
+  UpdateIconVisibility(extension_with_open_context_menu.value());
+}
+
 bool ExtensionsToolbarContainer::IsActionVisibleOnToolbar(
     const ToolbarActionViewController* action) const {
   const std::string& extension_id = action->GetId();
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
index 55da802a..41b35118 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
@@ -78,6 +78,11 @@
   views::Widget* GetAnchoredWidgetForExtensionForTesting(
       const std::string& extension_id);
 
+  base::Optional<extensions::ExtensionId>
+  GetExtensionWithOpenContextMenuForTesting() {
+    return extension_with_open_context_menu_id_;
+  }
+
   // ToolbarIconContainerView:
   void UpdateAllIcons() override;
   bool GetDropFormats(int* formats,
@@ -92,6 +97,8 @@
   ToolbarActionViewController* GetActionForId(
       const std::string& action_id) override;
   ToolbarActionViewController* GetPoppedOutAction() const override;
+  void OnContextMenuShown(ToolbarActionViewController* extension) override;
+  void OnContextMenuClosed(ToolbarActionViewController* extension) override;
   bool IsActionVisibleOnToolbar(
       const ToolbarActionViewController* action) const override;
   void UndoPopOut() override;
@@ -217,6 +224,8 @@
   ToolbarActionViewController* popped_out_action_ = nullptr;
   // The action that triggered the current popup, if any.
   ToolbarActionViewController* popup_owner_ = nullptr;
+  // Extension with an open context menu, if any.
+  base::Optional<extensions::ExtensionId> extension_with_open_context_menu_id_;
 
   // The widgets currently popped out and, for each, the extension it is
   // associated with. See AnchoredWidget.
diff --git a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
index b9d566b..23fdfc72 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
@@ -102,7 +102,7 @@
       TabSpecificContentSettings::FromWebContents(
           browser()->tab_strip_model()->GetActiveWebContents());
   content_settings->OnMediaStreamPermissionSet(
-      GURL::EmptyGURL(), mic_setting | camera_setting, std::string(),
+      GURL("https://example.com/"), mic_setting | camera_setting, std::string(),
       std::string(), std::string(), std::string());
 }
 
@@ -113,9 +113,6 @@
   TabSpecificContentSettings* content_settings =
       TabSpecificContentSettings::FromWebContents(web_contents);
   switch (content_type) {
-    case ContentSettingsType::GEOLOCATION:
-      content_settings->OnGeolocationPermissionSet(GURL::EmptyGURL(), false);
-      break;
     case ContentSettingsType::AUTOMATIC_DOWNLOADS: {
       // Automatic downloads are handled by DownloadRequestLimiter.
       DownloadRequestLimiter::TabDownloadState* tab_download_state =
@@ -127,20 +124,28 @@
           DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
       break;
     }
+    case ContentSettingsType::GEOLOCATION:
+      content_settings->OnGeolocationPermissionSet(GURL("https://example.com/"),
+                                                   false);
+      break;
+    case ContentSettingsType::MIDI_SYSEX:
+      content_settings->OnMidiSysExAccessBlocked(GURL("https://example.com/"));
+      break;
     case ContentSettingsType::POPUPS: {
-      GURL url(
+      ui_test_utils::NavigateToURL(
+          browser(),
           embedded_test_server()->GetURL("/popup_blocker/popup-many-10.html"));
-      ui_test_utils::NavigateToURL(browser(), url);
       EXPECT_TRUE(content::ExecuteScript(web_contents, std::string()));
       auto* helper = PopupBlockerTabHelper::FromWebContents(web_contents);
       // popup-many-10.html should generate 10 blocked popups.
       EXPECT_EQ(10u, helper->GetBlockedPopupsCount());
       break;
     }
-    case ContentSettingsType::PLUGINS: {
-      content_settings->OnContentBlocked(content_type);
+    case ContentSettingsType::PROTOCOL_HANDLERS:
+      content_settings->set_pending_protocol_handler(
+          ProtocolHandler::CreateProtocolHandler("mailto",
+                                                 GURL("https://example.com/")));
       break;
-    }
 
     default:
       // For all other content_types passed in, mark them as blocked.
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index e576222..21e401a9 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -929,7 +929,9 @@
     return false;
 
   views::View* image_view = content_setting_views_[index];
-  image_view->SetSize(gfx::Size(24, 24));
+  if (!image_view->GetVisible())
+    return false;
+
   image_view->OnKeyPressed(
       ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE));
   image_view->OnKeyReleased(
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index 34df0ff..1f9acf5f 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -407,10 +407,9 @@
   SkColor bubble_color =
       theme_provider->GetColor(ThemeProperties::COLOR_STATUS_BUBBLE);
   text->SetBackgroundColor(bubble_color);
-  // Text color is the foreground tab text color at 60% alpha.
-  text->SetEnabledColor(color_utils::AlphaBlend(
-      theme_provider->GetColor(ThemeProperties::COLOR_TAB_TEXT), bubble_color,
-      0.6f));
+  // Text color is the background tab text color, adjusted if required.
+  text->SetEnabledColor(
+      theme_provider->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB_TEXT));
 }
 
 const char* StatusBubbleViews::StatusView::GetClassName() const {
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 5f267ea..a3f799d 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -431,9 +431,7 @@
 }
 
 bool Tab::OnKeyPressed(const ui::KeyEvent& event) {
-  if ((event.key_code() == ui::VKEY_SPACE ||
-       event.key_code() == ui::VKEY_RETURN) &&
-      !IsSelected()) {
+  if (event.key_code() == ui::VKEY_RETURN && !IsSelected()) {
     controller_->SelectTab(this, event);
     return true;
   }
@@ -470,6 +468,14 @@
   return false;
 }
 
+bool Tab::OnKeyReleased(const ui::KeyEvent& event) {
+  if (event.key_code() == ui::VKEY_SPACE && !IsSelected()) {
+    controller_->SelectTab(this, event);
+    return true;
+  }
+  return false;
+}
+
 namespace {
 bool IsSelectionModifierDown(const ui::MouseEvent& event) {
 #if defined(OS_MACOSX)
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index d128c800d..d9a1b6b 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -84,6 +84,7 @@
   void Layout() override;
   const char* GetClassName() const override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
+  bool OnKeyReleased(const ui::KeyEvent& event) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
diff --git a/chrome/browser/ui/webui/downloads/downloads.mojom b/chrome/browser/ui/webui/downloads/downloads.mojom
index 4aa8113b..dfe2eae 100644
--- a/chrome/browser/ui/webui/downloads/downloads.mojom
+++ b/chrome/browser/ui/webui/downloads/downloads.mojom
@@ -47,6 +47,11 @@
   Cancel(string id);
   ClearAll();
   OpenDownloadsFolderRequiringGesture();
+
+  // Opens this download with the given |id| while it is being scanned by Safe
+  // Browsing. This completes the scan early. This requires a user gesture on
+  // the WebUI.
+  OpenDuringScanningRequiringGesture(string id);
 };
 
 interface Page {
diff --git a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
index 242fd8c..217db66c 100644
--- a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
@@ -71,6 +71,7 @@
   DOWNLOADS_DOM_EVENT_OPEN_FOLDER = 10,
   DOWNLOADS_DOM_EVENT_RESUME = 11,
   DOWNLOADS_DOM_EVENT_RETRY_DOWNLOAD = 12,
+  DOWNLOADS_DOM_EVENT_OPEN_DURING_SCANNING = 13,
   DOWNLOADS_DOM_EVENT_MAX
 };
 
@@ -355,6 +356,23 @@
   }
 }
 
+void DownloadsDOMHandler::OpenDuringScanningRequiringGesture(
+    const std::string& id) {
+  if (!GetWebUIWebContents()->HasRecentInteractiveInputEvent()) {
+    LOG(ERROR) << "OpenDownloadsFolderRequiringGesture received without recent "
+                  "user interaction";
+    return;
+  }
+
+  CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_OPEN_DURING_SCANNING);
+  download::DownloadItem* download = GetDownloadByStringId(id);
+  if (download) {
+    DownloadItemModel model(download);
+    model.SetOpenWhenComplete(true);
+    model.CompleteSafeBrowsingScan();
+  }
+}
+
 // DownloadsDOMHandler, private: --------------------------------------------
 
 content::DownloadManager* DownloadsDOMHandler::GetMainNotifierManager() const {
diff --git a/chrome/browser/ui/webui/downloads/downloads_dom_handler.h b/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
index a66442d..0e379455 100644
--- a/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
+++ b/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
@@ -61,6 +61,7 @@
   void Cancel(const std::string& id) override;
   void ClearAll() override;
   void OpenDownloadsFolderRequiringGesture() override;
+  void OpenDuringScanningRequiringGesture(const std::string& id) override;
 
  protected:
   // These methods are for mocking so that most of this class does not actually
diff --git a/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc b/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
index 888b9c96..feb29c69c 100644
--- a/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
@@ -275,6 +275,9 @@
         state = "DANGEROUS";
       } else if (download_item->IsMixedContent()) {
         state = "MIXED_CONTENT";
+      } else if (download_item->GetDangerType() ==
+                 download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING) {
+        state = "ASYNC_SCANNING";
       } else if (download_item->IsPaused()) {
         state = "PAUSED";
       } else {
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc
index 95892243..0f976c1 100644
--- a/chrome/browser/ui/webui/downloads/downloads_ui.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -123,6 +123,7 @@
       {"controlRemoveFromListAriaLabel", IDS_DOWNLOAD_LINK_REMOVE_ARIA_LABEL},
       {"controlRetry", IDS_DOWNLOAD_LINK_RETRY},
       {"controlledByUrl", IDS_DOWNLOAD_BY_EXTENSION_URL},
+      {"controlOpenNow", IDS_OPEN_DOWNLOAD_NOW},
       {"toastClearedAll", IDS_DOWNLOAD_TOAST_CLEARED_ALL},
       {"toastRemovedFromList", IDS_DOWNLOAD_TOAST_REMOVED_FROM_LIST},
       {"undo", IDS_DOWNLOAD_UNDO},
@@ -140,6 +141,8 @@
                              IDS_BLOCK_REASON_UNWANTED_DOWNLOAD);
   source->AddLocalizedString("mixedContentDownloadDesc",
                              IDS_BLOCK_REASON_MIXED_CONTENT);
+  source->AddLocalizedString("asyncScanningDownloadDesc",
+                             IDS_BLOCK_REASON_DEEP_SCANNING);
   if (browser_defaults::kDownloadPageHasShowInFolder)
     source->AddLocalizedString("controlShowInFolder", IDS_DOWNLOAD_LINK_SHOW);
 
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 3a1ad68..5aedd0c3 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1455,6 +1455,10 @@
     {"siteSettingsUsage", IDS_SETTINGS_SITE_SETTINGS_USAGE},
     {"siteSettingsUsageNone", IDS_SETTINGS_SITE_SETTINGS_USAGE_NONE},
     {"siteSettingsPermissions", IDS_SETTINGS_SITE_SETTINGS_PERMISSIONS},
+    {"siteSettingsPermissionsMore",
+     IDS_SETTINGS_SITE_SETTINGS_PERMISSIONS_MORE},
+    {"siteSettingsContent", IDS_SETTINGS_SITE_SETTINGS_CONTENT},
+    {"siteSettingsContentMore", IDS_SETTINGS_SITE_SETTINGS_CONTENT_MORE},
     {"siteSettingsSourceExtensionAllow",
      IDS_PAGE_INFO_PERMISSION_ALLOWED_BY_EXTENSION},
     {"siteSettingsSourceExtensionBlock",
diff --git a/chrome/browser/win/conflicts/module_inspector.cc b/chrome/browser/win/conflicts/module_inspector.cc
index 727e3143..852d4023 100644
--- a/chrome/browser/win/conflicts/module_inspector.cc
+++ b/chrome/browser/win/conflicts/module_inspector.cc
@@ -162,13 +162,6 @@
   return user_data_dir.Append(L"Module Info Cache");
 }
 
-void ModuleInspector::SetModuleInspectionResultForTesting(
-    const ModuleInfoKey& module_key,
-    ModuleInspectionResult inspection_result) {
-  AddInspectionResultToCache(module_key, inspection_result,
-                             &inspection_results_cache_);
-}
-
 void ModuleInspector::EnsureUtilWinServiceBound() {
   DCHECK(base::FeatureList::IsEnabled(kWinOOPInspectModuleFeature));
 
diff --git a/chrome/browser/win/conflicts/module_inspector.h b/chrome/browser/win/conflicts/module_inspector.h
index f8e54cc..f7bc50f 100644
--- a/chrome/browser/win/conflicts/module_inspector.h
+++ b/chrome/browser/win/conflicts/module_inspector.h
@@ -78,10 +78,6 @@
 
   static base::FilePath GetInspectionResultsCachePath();
 
-  void SetModuleInspectionResultForTesting(
-      const ModuleInfoKey& module_key,
-      ModuleInspectionResult inspection_result);
-
   void SetRemoteUtilWinForTesting(
       mojo::PendingRemote<chrome::mojom::UtilWin> remote) {
     test_remote_util_win_.Bind(std::move(remote));
diff --git a/chrome/chrome_cleaner/engines/controllers/uwe_engine_cleaner_wrapper.cc b/chrome/chrome_cleaner/engines/controllers/uwe_engine_cleaner_wrapper.cc
index d9c2c03..9ee5896 100644
--- a/chrome/chrome_cleaner/engines/controllers/uwe_engine_cleaner_wrapper.cc
+++ b/chrome/chrome_cleaner/engines/controllers/uwe_engine_cleaner_wrapper.cc
@@ -21,6 +21,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/win/registry.h"
 #include "chrome/chrome_cleaner/chrome_utils/extensions_util.h"
@@ -269,9 +270,10 @@
                         base::SequencedTaskRunnerHandle::Get()));
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  PostTask(FROM_HERE, {base::ThreadPool(), base::MayBlock()},
-           base::BindOnce(&UwEEngineCleanerWrapper::TryRemovePUPExtensions,
-                          base::Unretained(this), pup_ids));
+  base::ThreadPool::PostTask(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(&UwEEngineCleanerWrapper::TryRemovePUPExtensions,
+                     base::Unretained(this), pup_ids));
 
   cleaner_->Start(pup_ids,
                   base::BindOnce(&UwEEngineCleanerWrapper::OnDoneUwSCleanup,
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl
index 14ac8ba..253eac8 100644
--- a/chrome/common/extensions/api/autotest_private.idl
+++ b/chrome/common/extensions/api/autotest_private.idl
@@ -87,6 +87,11 @@
     FullscreenSearch
   };
 
+  enum OverviewStateType {
+   Shown,
+   Hidden
+  };
+
   enum MouseButton {
     Left,
     Middle,
@@ -841,6 +846,13 @@
     static void waitForLauncherState(LauncherStateType launcherState,
                                      VoidCallback callback);
 
+    // Wait until overview has transitioned to |overviewState|, if it is not in
+    // that state.
+    // |overviewState|: the target overview state.
+    // |callback|: called when overview has reached |overviewState|.
+    static void waitForOverviewState(OverviewStateType overviewState,
+                                     VoidCallback callback);
+
     // Creates a new desk if the maximum number of desks has not been reached.
     // |callback|: called to indicate success or failure.
     static void createNewDesk(DesksCallback callback);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 22112ce..193c916 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -940,6 +940,10 @@
 // Controlled by ParentAccessCodeConfig policy.
 const char kParentAccessCodeConfig[] = "child_user.parent_access_code.config";
 
+// List pref containing app activity and state for each application.
+const char kPerAppTimeLimitsAppActivities[] =
+    "child_user.per_app_time_limits.app_activities";
+
 // Dictionary pref containing the per-app time limits configuration for child
 // user. Controlled by PerAppTimeLimits policy.
 const char kPerAppTimeLimitsPolicy[] = "child_user.per_app_time_limits.policy";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 0a693f5..142f2ba 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -307,6 +307,7 @@
 extern const char kNetworkFileSharesPreconfiguredShares[];
 extern const char kMostRecentlyUsedNetworkFileShareURL[];
 extern const char kParentAccessCodeConfig[];
+extern const char kPerAppTimeLimitsAppActivities[];
 extern const char kPerAppTimeLimitsPolicy[];
 extern const char kPerAppTimeLimitsWhitelistPolicy[];
 extern const char kDeviceWallpaperImageFilePath[];
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
index 3ccb63b3..e2edf859 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -2230,17 +2230,34 @@
     }
   }
 
+  // Validates the authenticated user to either login to an existing user
+  // profile or fall back to creation of a new user profile. Below are few
+  // workflows.
+  //
+  // 1.) Add user flow with no existing association, found_sid should be empty,
+  //     falls through account creation
+  // 2.) Reauth user flow with no existing association, found_sid should be
+  //     empty, login attempt fails.
+  // 3.) Add user flow with existing association, found_sid exists,
+  //     logs into existing Windows account.
+  // 4.) Reauth user flow with existing association, found_sid exists,
+  //     logs into existing Windows account if found_sid matches reauth user
+  //     sid.
+  // 5.) Add user flow with cloud association, found_sid exists,
+  //     logs into existing account.
+  // 6.) Add/Reauth user flow with cloud association, found_sid exists,
+  //     logs into existing account if found_sid matches reauth user sid.
+  hr =
+      ValidateExistingUser(found_username, found_domain, found_sid, error_text);
+
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "ValidateExistingUser hr=" << putHR(hr);
+    return hr;
+  }
+
   // If an existing user associated to the gaia id or email address was found,
   // make sure that it is valid for this credential.
   if (found_sid[0]) {
-    hr = ValidateExistingUser(found_username, found_domain, found_sid,
-                              error_text);
-
-    if (FAILED(hr)) {
-      LOGFN(ERROR) << "ValidateExistingUser hr=" << putHR(hr);
-      return hr;
-    }
-
     // Update the name on the OS account if authenticated user has a different
     // name.
     base::string16 os_account_fullname;
diff --git a/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc b/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc
index 6c230ef1..692815d3 100644
--- a/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc
+++ b/chrome/credential_provider/gaiacp/reauth_credential_unittests.cc
@@ -28,6 +28,8 @@
 #include "chrome/credential_provider/test/test_credential.h"
 #include "content/public/common/content_switches.h"
 #include "google_apis/gaia/gaia_switches.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "net/base/escape.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace credential_provider {
@@ -526,6 +528,97 @@
 // 1. Is gem features enabled. If enabled, tos should be tested out.
 //    Otherwise, ToS shouldn't be set irrespective of the |kAcceptTos|
 //    registry entry.
+class GcpNormalReauthCredentialUserSidMismatch
+    : public GcpReauthCredentialGlsRunnerTest,
+      public ::testing::WithParamInterface<bool> {};
+
+TEST_P(GcpNormalReauthCredentialUserSidMismatch, ShouldFail) {
+  USES_CONVERSION;
+
+  bool is_non_matching_sid_empty = GetParam();
+
+  CredentialProviderSigninDialogTestDataStorage test_data_storage;
+
+  // Override registry to enable cloud association with google.
+  constexpr wchar_t kRegCloudAssociation[] = L"enable_cloud_association";
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(kRegCloudAssociation, 1));
+  ASSERT_EQ(S_OK, SetGlobalFlagForTesting(L"enable_verbose_logging", 1));
+
+  CComBSTR username = L"foo_bar";
+  CComBSTR full_name = A2COLE(test_data_storage.GetSuccessFullName().c_str());
+  CComBSTR password = A2COLE(test_data_storage.GetSuccessPassword().c_str());
+  CComBSTR email = A2COLE(test_data_storage.GetSuccessEmail().c_str());
+  CComBSTR domain = L"domain";
+
+  // Create a fake user to reauth.
+  CComBSTR sid;
+  ASSERT_EQ(S_OK,
+            fake_os_user_manager()->CreateTestOSUser(
+                OLE2CW(username), OLE2CW(password), OLE2CW(full_name),
+                L"comment", base::UTF8ToUTF16(test_data_storage.GetSuccessId()),
+                OLE2CW(email), OLE2CW(domain), &sid));
+
+  // Create provider and start logon.
+  Microsoft::WRL::ComPtr<ICredentialProviderCredential> cred;
+
+  // Create with invalid token handle response so that a reauth occurs.
+  SetDefaultTokenHandleResponse(kDefaultInvalidTokenHandleResponse);
+  ASSERT_EQ(S_OK, InitializeProviderAndGetCredential(1, &cred));
+  Microsoft::WRL::ComPtr<ITestCredential> test;
+  ASSERT_EQ(S_OK, cred.As(&test));
+
+  ASSERT_EQ(S_OK, test->SetGlsEmailAddress(std::string()));
+
+  // Delete the registry entries and create the environment where
+  // GCPW is installed on an AD joined machine and GetSerialization
+  // is triggered on a reauth credential.
+  RemoveAllUserProperties(OLE2CW(sid));
+
+  // The admin sdk users directory get URL.
+  std::string get_cd_user_url_ = base::StringPrintf(
+      "https://www.googleapis.com/admin/directory/v1/users/"
+      "%s?projection=full&viewType=domain_public",
+      net::EscapeUrlEncodedData(base::UTF16ToUTF8(OLE2CW(email)), true)
+          .c_str());
+  GaiaUrls* gaia_urls_ = GaiaUrls::GetInstance();
+  // Set token result as a valid access token.
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
+      FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
+
+  std::string admin_sdk_response;
+  CComBSTR different_user = L"different_foo_bar";
+  if (!is_non_matching_sid_empty) {
+    DWORD error;
+    ASSERT_EQ(S_OK, fake_os_user_manager()->AddUser(
+                        OLE2W(different_user), L"password", L"fullname",
+                        L"comment", true, L"domain", &sid, &error));
+  }
+
+  // Set valid response from admin sdk.
+  admin_sdk_response = base::StringPrintf(
+      "{\"customSchemas\": {\"Enhanced_desktop_security\": {\"AD_accounts\":"
+      " \"%ls/%ls\"}}}",
+      L"domain", OLE2CW(different_user));
+
+  fake_http_url_fetcher_factory()->SetFakeResponse(
+      GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
+      admin_sdk_response);
+
+  ASSERT_EQ(S_OK, StartLogonProcessAndWait());
+
+  // Logon process should fail with an internal error.
+  ASSERT_EQ(S_OK, FinishLogonProcess(false, false, IDS_ACCOUNT_IN_USE_BASE));
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         GcpNormalReauthCredentialUserSidMismatch,
+                         ::testing::Values(true, false));
+
+// Tests the normal reauth scenario.
+// 1. Is gem features enabled. If enabled, tos should be tested out.
+//    Otherwise, ToS shouldn't be set irrespective of the |kAcceptTos|
+//    registry entry.
 class GcpNormalReauthCredentialGlsRunnerTest
     : public GcpReauthCredentialGlsRunnerTest,
       public ::testing::WithParamInterface<bool> {};
diff --git a/chrome/elevation_service/BUILD.gn b/chrome/elevation_service/BUILD.gn
index 1c9fa30..1696ea74 100644
--- a/chrome/elevation_service/BUILD.gn
+++ b/chrome/elevation_service/BUILD.gn
@@ -48,6 +48,7 @@
     ":version_resources",
     "//base",
     "//build/win:default_exe_manifest",
+    "//chrome/install_static:install_static_util",
     "//chrome/install_static:primary_module",
     "//components/crx_file",
     "//third_party/zlib/google:zip",
@@ -57,15 +58,12 @@
 source_set("lib") {
   visibility = [ ":*" ]
 
-  public = [
-    "elevated_recovery_impl.h",
-    "elevator.h",
-    "service_main.h",
-  ]
-
   sources = [
     "elevated_recovery_impl.cc",
+    "elevated_recovery_impl.h",
     "elevator.cc",
+    "elevator.h",
+    "service_main.h",
     "service_main.cc",
   ]
 
@@ -73,12 +71,13 @@
   configs -= [ "//build/config/win:winver" ]
   configs += [ ":winver" ]
 
-  public_deps = [
+  deps = [
     ":elevation_service_idl",
     "//base",
+    "//chrome/install_static:install_static_util",
+    "//components/crx_file:crx_file",
+    "//third_party/zlib/google:zip",
   ]
-
-  deps = [ "//chrome/install_static:install_static_util" ]
 }
 
 process_version_rc_template("version_resources") {
@@ -109,6 +108,7 @@
     ":lib",
     "//base",
     "//base/test:test_support",
+    "//chrome/elevation_service:elevation_service_idl",
     "//chrome/install_static:install_static_util",
     "//chrome/install_static/test:test_support",
     "//components/crx_file",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/ThemeTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/ThemeTestUtils.java
index 249634f..efcb5a71 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/ThemeTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/ThemeTestUtils.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.test.util.browser;
 
+import android.annotation.TargetApi;
 import android.os.Build;
 
 import org.junit.Assert;
@@ -39,7 +40,10 @@
 
     /**
      * Asserts that the status bar color equals the passed-in color.
+     * Method is for Android L+ because it relies on Window#getStatusBarColor() which was introduced
+     * in L.
      */
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
     public static void assertStatusBarColor(ChromeActivity activity, int expectedColor) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
             expectedColor = ColorUtils.getDarkenedColorForStatusBar(expectedColor);
diff --git a/chrome/test/data/extensions/theme_test_toolbar_color_no_image/manifest.json b/chrome/test/data/extensions/theme_test_toolbar_color_no_image/manifest.json
index 501223e..80e455a1 100644
--- a/chrome/test/data/extensions/theme_test_toolbar_color_no_image/manifest.json
+++ b/chrome/test/data/extensions/theme_test_toolbar_color_no_image/manifest.json
@@ -5,7 +5,8 @@
   "theme": {
     "colors": {
       "frame": [ 255, 0, 255 ],
-      "toolbar": [ 0, 255, 0 ]
+      "toolbar": [ 0, 255, 0 ],
+      "toolbar_button_icon": [ 0, 0, 255 ]
       }
   },
   "version": "0.0.1"
diff --git a/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt
index 710fdd7..443d1a3 100644
--- a/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt
@@ -1,7 +1,7 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++description Name='Hello,<newline> world!<newline><newline>Goodbye,<newline> world!<newline>'
-++++++group IsControlElement=false
-++++++++description Name='This is some text abc<newline>def'
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Text Name='Hello,<newline> world!<newline><newline>Goodbye,<newline> world!<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='This is some text abc<newline>def'
diff --git a/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt
index a78adb4..5e72d6c6 100644
--- a/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt
@@ -1,5 +1,5 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++description Name='Hello, world!'
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Text Name='Hello, world!'
diff --git a/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt
index 2be1542..6f47bc9 100644
--- a/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt
@@ -1,12 +1,12 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++button Name='Hello'
-++++++++++description Name='Hello' IsControlElement=false
-++++++++description Name=', nice '
-++++++++button Name='meeting'
-++++++++++description Name='meeting' IsControlElement=false
-++++++++button Name=' y'
-++++++++++description Name=' y' IsControlElement=false
-++++++++description Name='ou'
\ No newline at end of file
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Custom Name='Hello'
+++++++++++Text Name='Hello' IsControlElement=false
+++++++++Text Name=', nice '
+++++++++Custom Name='meeting'
+++++++++++Text Name='meeting' IsControlElement=false
+++++++++Custom Name=' y'
+++++++++++Text Name=' y' IsControlElement=false
+++++++++Text Name='ou'
diff --git a/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt
index ca8c7255..e86141f0 100644
--- a/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt
@@ -1,7 +1,7 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++img Name='Image 1'
-++++++++img Name='Image 2'
-++++++++img Name='Image 3'
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Image Name='Image 1'
+++++++++Image Name='Image 2'
+++++++++Image Name='Image 3'
diff --git a/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt
index 21bd808..54f6fe4 100644
--- a/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt
@@ -1,8 +1,8 @@
-group
-++document Name='PDF document containing 2 pages'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++description Name='Page 1'
-++++region Name='Page 2'
-++++++group IsControlElement=false
-++++++++description Name='Page 2'
+Pane
+++Document Name='PDF document containing 2 pages'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Text Name='Page 1'
+++++Group Name='Page 2'
+++++++Group IsControlElement=false
+++++++++Text Name='Page 2'
diff --git a/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt
index 17a5570b..8d97687 100644
--- a/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt
@@ -1,13 +1,13 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++link Name='start first link start second link end second link end first link<newline>'
-++++++++++description Name='start first link start second link end second link end first link<newline>' IsControlElement=false
-++++++group IsControlElement=false
-++++++++link Name=' start second link end second link'
-++++++++++description Name=' start second link end second link' IsControlElement=false
-++++++++link Name='START FIRST LINK START SECOND LINK END FIRST LINK'
-++++++++++description Name='START FIRST LINK START SECOND LINK END FIRST LINK' IsControlElement=false
-++++++++link Name='START SECOND LINK END FIRST LINK END SECOND LINK'
-++++++++++description Name='START SECOND LINK END FIRST LINK END SECOND LINK' IsControlElement=false
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Hyperlink Name='start first link start second link end second link end first link<newline>'
+++++++++++Text Name='start first link start second link end second link end first link<newline>' IsControlElement=false
+++++++Group IsControlElement=false
+++++++++Hyperlink Name=' start second link end second link'
+++++++++++Text Name=' start second link end second link' IsControlElement=false
+++++++++Hyperlink Name='START FIRST LINK START SECOND LINK END FIRST LINK'
+++++++++++Text Name='START FIRST LINK START SECOND LINK END FIRST LINK' IsControlElement=false
+++++++++Hyperlink Name='START SECOND LINK END FIRST LINK END SECOND LINK'
+++++++++++Text Name='START SECOND LINK END FIRST LINK END SECOND LINK' IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt
index 133962a..1eed1b2 100644
--- a/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt
@@ -1,13 +1,13 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++heading IsControlElement=false
-++++++++description Name='Heading<newline>' IsControlElement=false
-++++++group IsControlElement=false
-++++++++description Name='This is a small pdf file:<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Lorem Ipsum is simply dummy text of the printing and typesetting industry.<newline>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.<newline>'
-++++++group IsControlElement=false
-++++++++description Name='It has survived not only five centuries, but also the leap into electronic typesetting,<newline>remaining essentially unchanged. It was popularised in the 1960s with the release of<newline>Letraset sheets containing Lorem Ipsum passages, and more recently with desktop<newline>publishing software like Aldus PageMaker including versions of Lorem Ipsum.<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots<newline>in a piece of classical Latin literature from 45 BC, making it over 2000 years old.'
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Text IsControlElement=false
+++++++++Text Name='Heading<newline>' IsControlElement=false
+++++++Group IsControlElement=false
+++++++++Text Name='This is a small pdf file:<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Lorem Ipsum is simply dummy text of the printing and typesetting industry.<newline>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='It has survived not only five centuries, but also the leap into electronic typesetting,<newline>remaining essentially unchanged. It was popularised in the 1960s with the release of<newline>Letraset sheets containing Lorem Ipsum passages, and more recently with desktop<newline>publishing software like Aldus PageMaker including versions of Lorem Ipsum.<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots<newline>in a piece of classical Latin literature from 45 BC, making it over 2000 years old.'
diff --git a/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt
index 2dfda340..acfc618 100644
--- a/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt
@@ -1,25 +1,25 @@
-group
-++document Name='PDF document containing 2 pages'
-++++region Name='Page 1'
-++++++heading IsControlElement=false
-++++++++description Name='Link Annotations - Page 1<newline>' IsControlElement=false
-++++++heading IsControlElement=false
-++++++++link Name='Link with destination to second page<newline>'
-++++++++++description Name='Link with destination to second page<newline>' IsControlElement=false
-++++++group IsControlElement=false
-++++++++link Name='PDF Reference, Version 1.7,'
-++++++++++description Name='PDF Reference, Version 1.7,' IsControlElement=false
-++++++++description Name=' Section 8.4.5 defines Annotations<newline>3. Hello World<newline>'
-++++++++link Name='https://pdfium.googlesource.com/pdfium'
-++++++++++description Name='https://pdfium.googlesource.com/pdfium' IsControlElement=false
-++++++++description Name=' is link in plain text, not link annotation. These are referred to<newline>as '
-++++++++link Name='WebLinks in PDFium'
-++++++++++description Name='WebLinks in PDFium' IsControlElement=false
-++++++++description Name='.'
-++++++++link
-++++++++img Name='Image 1'
-++++++++img Name='Unlabeled graphic'
-++++++++img Name='Unlabeled graphic'
-++++region Name='Page 2'
-++++++group IsControlElement=false
-++++++++description Name='Second Page'
+Pane
+++Document Name='PDF document containing 2 pages'
+++++Group Name='Page 1'
+++++++Text IsControlElement=false
+++++++++Text Name='Link Annotations - Page 1<newline>' IsControlElement=false
+++++++Text IsControlElement=false
+++++++++Hyperlink Name='Link with destination to second page<newline>'
+++++++++++Text Name='Link with destination to second page<newline>' IsControlElement=false
+++++++Group IsControlElement=false
+++++++++Hyperlink Name='PDF Reference, Version 1.7,'
+++++++++++Text Name='PDF Reference, Version 1.7,' IsControlElement=false
+++++++++Text Name=' Section 8.4.5 defines Annotations<newline>3. Hello World<newline>'
+++++++++Hyperlink Name='https://pdfium.googlesource.com/pdfium'
+++++++++++Text Name='https://pdfium.googlesource.com/pdfium' IsControlElement=false
+++++++++Text Name=' is link in plain text, not link annotation. These are referred to<newline>as '
+++++++++Hyperlink Name='WebLinks in PDFium'
+++++++++++Text Name='WebLinks in PDFium' IsControlElement=false
+++++++++Text Name='.'
+++++++++Hyperlink
+++++++++Image Name='Image 1'
+++++++++Image Name='Unlabeled graphic'
+++++++++Image Name='Unlabeled graphic'
+++++Group Name='Page 2'
+++++++Group IsControlElement=false
+++++++++Text Name='Second Page'
diff --git a/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt
index 56a02f5..76b3df4 100644
--- a/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt
@@ -1,5 +1,5 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++description Name='Hello world! One word equals to one text run.'
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Text Name='Hello world! One word equals to one text run.'
diff --git a/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt
index 51645161..68f0ef0 100644
--- a/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt
@@ -1,11 +1,11 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++description Name='Case 1<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Case 2<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Case 3<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Case 4'
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Text Name='Case 1<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Case 2<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Case 3<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Case 4'
diff --git a/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt
index 311e300c..f3fd405 100644
--- a/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt
+++ b/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt
@@ -1,17 +1,17 @@
-group
-++document Name='PDF document containing 1 page'
-++++region Name='Page 1'
-++++++group IsControlElement=false
-++++++++description Name='Hello, '
-++++++++link Name='http://yahoo.com'
-++++++++++description Name='http://yahoo.com' IsControlElement=false
-++++++++description Name='! nice meeting you<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Goodbye, '
-++++++++link Name='http://bing.com'
-++++++++++description Name='http://bing.com' IsControlElement=false
-++++++++description Name='! nice meeting you<newline>'
-++++++group IsControlElement=false
-++++++++description Name='Bye, '
-++++++++link Name='http://google.com'
-++++++++++description Name='http://google.com' IsControlElement=false
+Pane
+++Document Name='PDF document containing 1 page'
+++++Group Name='Page 1'
+++++++Group IsControlElement=false
+++++++++Text Name='Hello, '
+++++++++Hyperlink Name='http://yahoo.com'
+++++++++++Text Name='http://yahoo.com' IsControlElement=false
+++++++++Text Name='! nice meeting you<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Goodbye, '
+++++++++Hyperlink Name='http://bing.com'
+++++++++++Text Name='http://bing.com' IsControlElement=false
+++++++++Text Name='! nice meeting you<newline>'
+++++++Group IsControlElement=false
+++++++++Text Name='Bye, '
+++++++++Hyperlink Name='http://google.com'
+++++++++++Text Name='http://google.com' IsControlElement=false
diff --git a/chrome/test/data/prerender/prerender_events_common.js b/chrome/test/data/prerender/prerender_events_common.js
index 6d125e1..8416e170 100644
--- a/chrome/test/data/prerender/prerender_events_common.js
+++ b/chrome/test/data/prerender/prerender_events_common.js
@@ -29,7 +29,7 @@
 function PrerenderEventHandler(index, ev) {
   // Check for errors.
   if (ev.type == 'webkitprerenderstart') {
-    // No event may preceed start.
+    // No event may precede start.
     if (GetPrerenderEventCount(index, 'webkitprerenderstart') ||
         GetPrerenderEventCount(index, 'webkitprerenderdomcontentloaded') ||
         GetPrerenderEventCount(index, 'webkitprerenderload') ||
diff --git a/chrome/test/data/webui/settings/site_settings_page_test.js b/chrome/test/data/webui/settings/site_settings_page_test.js
index 9a9c434..9459684 100644
--- a/chrome/test/data/webui/settings/site_settings_page_test.js
+++ b/chrome/test/data/webui/settings/site_settings_page_test.js
@@ -9,14 +9,22 @@
   /** @type {SettingsSiteSettingsPageElement} */
   let page;
 
-  setup(function() {
+  suiteSetup(function() {
+    loadTimeData.overrideValues({
+      privacySettingsRedesignEnabled: false,
+    });
+  });
+
+  function setupPage() {
     testBrowserProxy = new TestMetricsBrowserProxy();
     settings.MetricsBrowserProxyImpl.instance_ = testBrowserProxy;
     PolymerTest.clearBody();
     page = document.createElement('settings-site-settings-page');
     document.body.appendChild(page);
     Polymer.dom.flush();
-  });
+  }
+
+  setup(setupPage);
 
   teardown(function() {
     page.remove();
@@ -55,288 +63,62 @@
             settings.ContentSetting.IMPORTANT_CONTENT, 'a', 'b', 'c'));
   });
 
+  async function testClicks(listElement) {
+    const triggers = listElement.shadowRoot.querySelectorAll('cr-link-row');
+    assertTrue(triggers.length > 0);
+    const domRepeat = listElement.$$('dom-repeat').template;
+    for (const trigger of triggers) {
+      const data = Polymer.Templatize.modelForElement(domRepeat, trigger);
+      assertTrue(!!data);
+      trigger.click();
+      const result =
+          await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
+      assertEquals(
+          settings.SettingsPageInteractions[`PRIVACY_${data.item.route}`],
+          result);
+      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
+      testBrowserProxy.reset();
+    }
+  }
+
   test('LogAllSiteSettingsPageClicks', async function() {
+    // Test the allSites case.
     page.$$('#allSites').click();
-    let result =
+    const result =
         await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
     assertEquals(
         settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_ALL, result);
-
     settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
     testBrowserProxy.reset();
 
-    page.$$(`#${settings.ContentSettingsTypes.COOKIES}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
+    // Test all remaining items.
+    const lists =
+        page.shadowRoot.querySelectorAll('settings-site-settings-list');
+    assertEquals(1, lists.length);
+    await testClicks(lists[0]);
+  });
+
+  test('LogAllSiteSettingsPageClicks_Redesign', async function() {
+    loadTimeData.overrideValues({
+      privacySettingsRedesignEnabled: true,
+    });
+    setupPage();
+
+    // Test the allSites case.
+    page.$$('#allSites').click();
+    const result =
+        await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
     assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_COOKIES,
-        result);
-
+        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_ALL, result);
     settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
     testBrowserProxy.reset();
 
-    page.$$(`#${settings.ContentSettingsTypes.GEOLOCATION}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_LOCATION,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.CAMERA}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_CAMERA, result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.MIC}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_MICROPHONE,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.SENSORS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_SENSORS,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.NOTIFICATIONS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_NOTIFICATIONS,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.JAVASCRIPT}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_JAVASCRIPT,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.PLUGINS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_FLASH, result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.IMAGES}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_IMAGES, result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.POPUPS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_POPUPS, result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.BACKGROUND_SYNC}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_BACKGROUND_SYNC,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.SOUND}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_SOUND, result);
-
-    if (loadTimeData.getBoolean('enableSafeBrowsingSubresourceFilter')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.ADS}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_ADS, result);
-    }
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.AUTOMATIC_DOWNLOADS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions
-            .PRIVACY_SITE_SETTINGS_AUTOMATIC_DOWNLOADS,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions
-            .PRIVACY_SITE_SETTINGS_UNSANDBOXED_PLUGINS,
-        result);
-
-    if (!loadTimeData.getBoolean('isGuest')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.PROTOCOL_HANDLERS}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_HANDLERS,
-          result);
-    }
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.MIDI_DEVICES}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_MIDI_DEVICES,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.ZOOM_LEVELS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_ZOOM_LEVELS,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.USB_DEVICES}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_USB_DEVICES,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.SERIAL_PORTS}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_SERIAL_PORTS,
-        result);
-
-    if (loadTimeData.getBoolean('enableNativeFileSystemWriteContentSetting')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.NATIVE_FILE_SYSTEM_WRITE}`)
-          .click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions
-              .PRIVACY_SITE_SETTINGS_NATIVE_FILE_SYSTEM_WRITE,
-          result);
-    }
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$('#pdfDocuments').click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_PDF_DOCUMENTS,
-        result);
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    if (cr.isChromeOS) {
-      page.$$(`#${settings.ContentSettingsTypes.PROTECTED_CONTENT}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions
-              .PRIVACY_SITE_SETTINGS_PROTECTED_CONTENT,
-          result);
-    }
-
-    settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-    testBrowserProxy.reset();
-
-    page.$$(`#${settings.ContentSettingsTypes.CLIPBOARD}`).click();
-    result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-    assertEquals(
-        settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_CLIPBOARD,
-        result);
-
-    if (loadTimeData.getBoolean('enablePaymentHandlerContentSetting')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.PAYMENT_HANDLER}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions
-              .PRIVACY_SITE_SETTINGS_PAYMENT_HANDLER,
-          result);
-    }
-
-    if (loadTimeData.getBoolean('enableInsecureContentContentSetting')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.MIXEDSCRIPT}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_MIXEDSCRIPT,
-          result);
-    }
-
-    if (loadTimeData.getBoolean('enableExperimentalWebPlatformFeatures')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.BLUETOOTH_SCANNING}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions
-              .PRIVACY_SITE_SETTINGS_BLUETOOTH_SCANNING,
-          result);
-    }
-
-    if (loadTimeData.getBoolean('enableWebXrContentSetting')) {
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.AR}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_AR, result);
-
-
-      settings.Router.getInstance().navigateTo(settings.routes.SITE_SETTINGS);
-      testBrowserProxy.reset();
-
-      page.$$(`#${settings.ContentSettingsTypes.VR}`).click();
-      result = await testBrowserProxy.whenCalled('recordSettingsPageHistogram');
-      assertEquals(
-          settings.SettingsPageInteractions.PRIVACY_SITE_SETTINGS_VR, result);
+    // Test all remaining items (which are spread over four separate lists).
+    const lists =
+        page.shadowRoot.querySelectorAll('settings-site-settings-list');
+    assertEquals(4, lists.length);
+    for (const list of lists) {
+      await testClicks(list);
     }
   });
 });
diff --git a/chrome/updater/win/action_handler.cc b/chrome/updater/win/action_handler.cc
index 0457f0c9..cafa45754 100644
--- a/chrome/updater/win/action_handler.cc
+++ b/chrome/updater/win/action_handler.cc
@@ -16,6 +16,7 @@
 #include "base/process/launch.h"
 #include "base/process/process.h"
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/updater/action_handler.h"
@@ -48,9 +49,9 @@
                            const std::string&,
                            Callback callback) {
   DCHECK(!action.empty());
-  PostTaskAndReplyWithResult(
+  base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(),
+      {base::MayBlock(), base::WithBaseSyncPrimitives(),
        base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&ActionHandler::RunCommand, action),
diff --git a/chromecast/browser/cast_web_contents_browsertest.cc b/chromecast/browser/cast_web_contents_browsertest.cc
index 516e194..ddb22cd 100644
--- a/chromecast/browser/cast_web_contents_browsertest.cc
+++ b/chromecast/browser/cast_web_contents_browsertest.cc
@@ -676,6 +676,48 @@
   run_loop->Run();
 }
 
+IN_PROC_BROWSER_TEST_F(CastWebContentsBrowserTest, LocationRedirectLifecycle) {
+  auto run_loop = std::make_unique<base::RunLoop>();
+  auto quit_closure = [&run_loop]() {
+    if (run_loop->running()) {
+      run_loop->QuitWhenIdle();
+    }
+  };
+
+  // ===========================================================================
+  // Test: When the app redirects to another url via window.location. Another
+  // navigation will be committed. LOADING -> LOADED -> LOADING -> LOADED state
+  // trasition is expected.
+  // ===========================================================================
+  embedded_test_server()->ServeFilesFromSourceDirectory(GetTestDataPath());
+  StartTestServer();
+
+  {
+    InSequence seq;
+    EXPECT_CALL(
+        mock_cast_wc_observer_,
+        OnPageStateChanged(CheckPageState(
+            cast_web_contents_.get(), CastWebContents::PageState::LOADING)));
+    EXPECT_CALL(
+        mock_cast_wc_observer_,
+        OnPageStateChanged(CheckPageState(cast_web_contents_.get(),
+                                          CastWebContents::PageState::LOADED)));
+    EXPECT_CALL(
+        mock_cast_wc_observer_,
+        OnPageStateChanged(CheckPageState(
+            cast_web_contents_.get(), CastWebContents::PageState::LOADING)));
+    EXPECT_CALL(
+        mock_cast_wc_observer_,
+        OnPageStateChanged(CheckPageState(cast_web_contents_.get(),
+                                          CastWebContents::PageState::LOADED)))
+        .WillOnce(InvokeWithoutArgs(quit_closure));
+  }
+
+  cast_web_contents_->LoadUrl(
+      embedded_test_server()->GetURL("/location_redirect.html"));
+  run_loop->Run();
+}
+
 IN_PROC_BROWSER_TEST_F(CastWebContentsBrowserTest, NotifyMissingResource) {
   auto run_loop = std::make_unique<base::RunLoop>();
   auto quit_closure = [&run_loop]() {
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc
index 9009cd5c..21d3c2f 100644
--- a/chromecast/browser/cast_web_contents_impl.cc
+++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -598,6 +598,26 @@
 
 void CastWebContentsImpl::ReadyToCommitNavigation(
     content::NavigationHandle* navigation_handle) {
+  DCHECK(navigation_handle);
+  if (!web_contents_ || closing_ || stopped_)
+    return;
+  if (!navigation_handle->IsInMainFrame())
+    return;
+
+  // Main frame has begun navigating/loading.
+  OnPageLoading();
+  start_loading_ticks_ = base::TimeTicks::Now();
+  GURL loading_url;
+  content::NavigationEntry* nav_entry =
+      web_contents()->GetController().GetVisibleEntry();
+  if (nav_entry) {
+    loading_url = nav_entry->GetVirtualURL();
+  }
+  TracePageLoadBegin(loading_url);
+  UpdatePageState();
+  DCHECK_EQ(page_state_, PageState::LOADING);
+  NotifyPageState();
+
   if (before_load_scripts_.empty())
     return;
 
diff --git a/chromecast/browser/test/data/location_redirect.html b/chromecast/browser/test/data/location_redirect.html
new file mode 100644
index 0000000..0b4d466
--- /dev/null
+++ b/chromecast/browser/test/data/location_redirect.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+    <script type="text/javascript">
+    window.location = "about:blank";
+    </script>
+</body>
diff --git a/chromeos/components/drivefs/BUILD.gn b/chromeos/components/drivefs/BUILD.gn
index 0aeb117..a804586 100644
--- a/chromeos/components/drivefs/BUILD.gn
+++ b/chromeos/components/drivefs/BUILD.gn
@@ -30,12 +30,12 @@
     "//chromeos/disks",
     "//components/account_id",
     "//components/drive",
+    "//components/signin/public/identity_manager",
     "//dbus",
     "//google_apis",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/platform",
     "//net",
-    "//services/identity/public/mojom",
     "//services/network/public/cpp:cpp",
   ]
   defines = [ "IS_DRIVEFS_IMPL" ]
@@ -77,10 +77,11 @@
     "//components/account_id",
     "//components/drive",
     "//components/invalidation/impl:test_support",
+    "//components/signin/public/identity_manager",
+    "//components/signin/public/identity_manager:test_support",
     "//mojo/public/cpp/bindings",
     "//net",
     "//net:test_support",
-    "//services/identity/public/mojom",
     "//services/network:test_support",
     "//services/network/public/cpp:cpp",
     "//testing/gmock",
diff --git a/chromeos/components/drivefs/DEPS b/chromeos/components/drivefs/DEPS
index e415f038..e1d69fe 100644
--- a/chromeos/components/drivefs/DEPS
+++ b/chromeos/components/drivefs/DEPS
@@ -1,6 +1,6 @@
 include_rules = [
   "+components/drive",
   "+components/invalidation/impl/fake_invalidation_service.h",
+  "+components/signin",
   "+mojo/public",
-  "+services/identity/public",
 ]
diff --git a/chromeos/components/drivefs/drivefs_auth.cc b/chromeos/components/drivefs/drivefs_auth.cc
index 00be867..8511be4 100644
--- a/chromeos/components/drivefs/drivefs_auth.cc
+++ b/chromeos/components/drivefs/drivefs_auth.cc
@@ -6,6 +6,11 @@
 
 #include "base/bind.h"
 #include "components/account_id/account_id.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/consent_level.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
+#include "google_apis/gaia/google_service_auth_error.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace drivefs {
@@ -23,7 +28,7 @@
       timer_(std::move(timer)),
       delegate_(delegate) {}
 
-DriveFsAuth::~DriveFsAuth() {}
+DriveFsAuth::~DriveFsAuth() = default;
 
 base::Optional<std::string> DriveFsAuth::GetCachedAccessToken() {
   const auto& token = GetOrResetCachedToken(true);
@@ -48,35 +53,32 @@
     return;
   }
 
+  signin::IdentityManager* identity_manager = delegate_->GetIdentityManager();
+  if (!identity_manager) {
+    std::move(callback).Run(mojom::AccessTokenStatus::kAuthError, "");
+    return;
+  }
   get_access_token_callback_ = std::move(callback);
-  timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(30),
-                base::BindOnce(&DriveFsAuth::AuthTimeout,
-                               weak_ptr_factory_.GetWeakPtr()));
-  GetIdentityAccessor()->GetUnconsentedPrimaryAccountWhenAvailable(
-      base::BindOnce(&DriveFsAuth::AccountReady,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-void DriveFsAuth::AccountReady(const CoreAccountId& account_id,
-                               const std::string& gaia,
-                               const std::string& email,
-                               const identity::AccountState& state) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  weak_ptr_factory_.InvalidateWeakPtrs();
-  timer_->Stop();
-  GetIdentityAccessor()->GetAccessToken(
-      account_id, {"https://www.googleapis.com/auth/drive"},
-      kIdentityConsumerId,
-      base::BindOnce(&DriveFsAuth::GotChromeAccessToken,
-                     base::Unretained(this)));
+  // Timer is cancelled when it is destroyed, so use base::Unretained().
+  timer_->Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(30),
+      base::BindOnce(&DriveFsAuth::AuthTimeout, base::Unretained(this)));
+  std::set<std::string> scopes({"https://www.googleapis.com/auth/drive"});
+  access_token_fetcher_ =
+      std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
+          kIdentityConsumerId, identity_manager, scopes,
+          base::BindOnce(&DriveFsAuth::GotChromeAccessToken,
+                         base::Unretained(this)),
+          signin::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable,
+          signin::ConsentLevel::kNotRequired);
 }
 
 void DriveFsAuth::GotChromeAccessToken(
-    const base::Optional<std::string>& access_token,
-    base::Time expiration_time,
-    const GoogleServiceAuthError& error) {
+    GoogleServiceAuthError error,
+    signin::AccessTokenInfo access_token_info) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!access_token) {
+  timer_->Stop();
+  if (error.state() != GoogleServiceAuthError::NONE) {
     std::move(get_access_token_callback_)
         .Run(error.IsPersistentError()
                  ? mojom::AccessTokenStatus::kAuthError
@@ -84,9 +86,9 @@
              "");
     return;
   }
-  UpdateCachedToken(*access_token, expiration_time);
+  UpdateCachedToken(access_token_info.token, access_token_info.expiration_time);
   std::move(get_access_token_callback_)
-      .Run(mojom::AccessTokenStatus::kSuccess, *access_token);
+      .Run(mojom::AccessTokenStatus::kSuccess, access_token_info.token);
 }
 
 const std::string& DriveFsAuth::GetOrResetCachedToken(bool use_cached) {
@@ -104,18 +106,8 @@
 
 void DriveFsAuth::AuthTimeout() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  weak_ptr_factory_.InvalidateWeakPtrs();
   std::move(get_access_token_callback_)
       .Run(mojom::AccessTokenStatus::kAuthError, "");
 }
 
-identity::mojom::IdentityAccessor* DriveFsAuth::GetIdentityAccessor() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!identity_accessor_) {
-    delegate_->BindIdentityAccessor(
-        identity_accessor_.BindNewPipeAndPassReceiver());
-  }
-  return identity_accessor_.get();
-}
-
 }  // namespace drivefs
diff --git a/chromeos/components/drivefs/drivefs_auth.h b/chromeos/components/drivefs/drivefs_auth.h
index 3008fdf..e1f79305 100644
--- a/chromeos/components/drivefs/drivefs_auth.h
+++ b/chromeos/components/drivefs/drivefs_auth.h
@@ -11,20 +11,23 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "base/time/clock.h"
 #include "base/timer/timer.h"
 #include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/identity/public/mojom/identity_accessor.mojom.h"
 
 class AccountId;
+class GoogleServiceAuthError;
 
 namespace network {
 class SharedURLLoaderFactory;
 }  // namespace network
 
+namespace signin {
+struct AccessTokenInfo;
+class IdentityManager;
+class PrimaryAccountAccessTokenFetcher;
+}  // namespace signin
+
 namespace drivefs {
 
 class COMPONENT_EXPORT(DRIVEFS) DriveFsAuth {
@@ -36,8 +39,7 @@
 
     virtual scoped_refptr<network::SharedURLLoaderFactory>
     GetURLLoaderFactory() = 0;
-    virtual void BindIdentityAccessor(
-        mojo::PendingReceiver<identity::mojom::IdentityAccessor> receiver) = 0;
+    virtual signin::IdentityManager* GetIdentityManager() = 0;
     virtual const AccountId& GetAccountId() = 0;
     virtual std::string GetObfuscatedAccountId() = 0;
     virtual bool IsMetricsCollectionEnabled() = 0;
@@ -71,14 +73,8 @@
       mojom::DriveFsDelegate::GetAccessTokenCallback callback);
 
  private:
-  void AccountReady(const CoreAccountId& account_id,
-                    const std::string& gaia,
-                    const std::string& email,
-                    const identity::AccountState& state);
-
-  void GotChromeAccessToken(const base::Optional<std::string>& access_token,
-                            base::Time expiration_time,
-                            const GoogleServiceAuthError& error);
+  void GotChromeAccessToken(GoogleServiceAuthError error,
+                            signin::AccessTokenInfo access_token_info);
 
   const std::string& GetOrResetCachedToken(bool use_cached);
 
@@ -86,16 +82,14 @@
 
   void AuthTimeout();
 
-  identity::mojom::IdentityAccessor* GetIdentityAccessor();
-
   SEQUENCE_CHECKER(sequence_checker_);
   const base::Clock* const clock_;
   const base::FilePath profile_path_;
   const std::unique_ptr<base::OneShotTimer> timer_;
   Delegate* const delegate_;
 
-  // The connection to the identity service. Access via |GetIdentityAccessor()|.
-  mojo::Remote<identity::mojom::IdentityAccessor> identity_accessor_;
+  std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
+      access_token_fetcher_;
 
   // Pending callback for an in-flight GetAccessToken request.
   mojom::DriveFsDelegate::GetAccessTokenCallback get_access_token_callback_;
@@ -103,7 +97,6 @@
   std::string last_token_;
   base::Time last_token_expiry_;
 
-  base::WeakPtrFactory<DriveFsAuth> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(DriveFsAuth);
 };
 
diff --git a/chromeos/components/drivefs/drivefs_auth_unittest.cc b/chromeos/components/drivefs/drivefs_auth_unittest.cc
index 55cecce0..9cfbf847 100644
--- a/chromeos/components/drivefs/drivefs_auth_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_auth_unittest.cc
@@ -5,6 +5,7 @@
 #include "chromeos/components/drivefs/drivefs_auth.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_split.h"
@@ -13,9 +14,10 @@
 #include "base/test/task_environment.h"
 #include "base/timer/mock_timer.h"
 #include "components/account_id/account_id.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "google_apis/gaia/google_service_auth_error.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
-#include "services/identity/public/mojom/identity_accessor.mojom-test-utils.h"
-#include "services/identity/public/mojom/identity_service.mojom.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -25,11 +27,14 @@
 
 using testing::_;
 
+constexpr char kTestEmail[] = "test@example.com";
+constexpr base::TimeDelta kTokenLifetime = base::TimeDelta::FromHours(1);
+
 class AuthDelegateImpl : public DriveFsAuth::Delegate {
  public:
-  AuthDelegateImpl(identity::mojom::IdentityService* identity_service,
+  AuthDelegateImpl(signin::IdentityManager* identity_manager,
                    const AccountId& account_id)
-      : identity_service_(identity_service), account_id_(account_id) {}
+      : identity_manager_(identity_manager), account_id_(account_id) {}
 
   ~AuthDelegateImpl() override = default;
 
@@ -39,10 +44,8 @@
       override {
     return nullptr;
   }
-  void BindIdentityAccessor(
-      mojo::PendingReceiver<identity::mojom::IdentityAccessor> receiver)
-      override {
-    identity_service_->BindIdentityAccessor(std::move(receiver));
+  signin::IdentityManager* GetIdentityManager() override {
+    return identity_manager_;
   }
   const AccountId& GetAccountId() override { return account_id_; }
   std::string GetObfuscatedAccountId() override {
@@ -51,95 +54,25 @@
 
   bool IsMetricsCollectionEnabled() override { return false; }
 
-  identity::mojom::IdentityService* const identity_service_;
+  signin::IdentityManager* const identity_manager_;
   const AccountId account_id_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthDelegateImpl);
 };
 
-class MockIdentityAccessor {
- public:
-  MOCK_METHOD3(
-      GetAccessToken,
-      std::pair<base::Optional<std::string>, GoogleServiceAuthError::State>(
-          const CoreAccountId& account_id,
-          const ::identity::ScopeSet& scopes,
-          const std::string& consumer_id));
-
-  mojo::ReceiverSet<identity::mojom::IdentityAccessor>* receivers_ = nullptr;
-};
-
-class FakeIdentityService
-    : public identity::mojom::IdentityAccessorInterceptorForTesting,
-      public identity::mojom::IdentityService {
- public:
-  explicit FakeIdentityService(MockIdentityAccessor* mock,
-                               const base::Clock* clock)
-      : mock_(mock), clock_(clock) {
-    mock_->receivers_ = &receivers_;
-  }
-
-  ~FakeIdentityService() override { mock_->receivers_ = nullptr; }
-
-  void set_auth_enabled(bool enabled) { auth_enabled_ = enabled; }
-
- private:
-  // identity::mojom::IdentityService:
-  void BindIdentityAccessor(
-      mojo::PendingReceiver<identity::mojom::IdentityAccessor> receiver)
-      override {
-    receivers_.Add(this, std::move(receiver));
-  }
-
-  // identity::mojom::IdentityAccessorInterceptorForTesting overrides:
-  void GetUnconsentedPrimaryAccountWhenAvailable(
-      GetUnconsentedPrimaryAccountWhenAvailableCallback callback) override {
-    if (!auth_enabled_) {
-      return;
-    }
-    auto account_id = AccountId::FromUserEmailGaiaId("test@example.com", "ID");
-    std::move(callback).Run(CoreAccountId(account_id.GetUserEmail()),
-                            account_id.GetGaiaId(), account_id.GetUserEmail(),
-                            {});
-  }
-
-  void GetAccessToken(const CoreAccountId& account_id,
-                      const ::identity::ScopeSet& scopes,
-                      const std::string& consumer_id,
-                      GetAccessTokenCallback callback) override {
-    auto result = mock_->GetAccessToken(account_id, scopes, consumer_id);
-    std::move(callback).Run(std::move(result.first),
-                            clock_->Now() + base::TimeDelta::FromSeconds(1),
-                            GoogleServiceAuthError(result.second));
-  }
-
-  IdentityAccessor* GetForwardingInterface() override {
-    NOTREACHED();
-    return nullptr;
-  }
-
-  MockIdentityAccessor* const mock_;
-  const base::Clock* const clock_;
-  mojo::ReceiverSet<identity::mojom::IdentityAccessor> receivers_;
-  bool auth_enabled_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeIdentityService);
-};
-
 class DriveFsAuthTest : public ::testing::Test {
  public:
-  DriveFsAuthTest() : kTestAccountId("test@example.com") {}
+  DriveFsAuthTest() = default;
 
  protected:
   void SetUp() override {
     clock_.SetNow(base::Time::Now());
-    identity_service_ = std::make_unique<FakeIdentityService>(
-        &mock_identity_accessor_, &clock_);
+    identity_test_env_.MakeUnconsentedPrimaryAccountAvailable(kTestEmail);
     auto timer = std::make_unique<base::MockOneShotTimer>();
     timer_ = timer.get();
     delegate_ = std::make_unique<AuthDelegateImpl>(
-        identity_service_.get(),
-        AccountId::FromUserEmailGaiaId("test@example.com", "ID"));
+        identity_test_env_.identity_manager(),
+        AccountId::FromUserEmailGaiaId(kTestEmail, "ID"));
     auth_ = std::make_unique<DriveFsAuth>(&clock_,
                                           base::FilePath("/path/to/profile"),
                                           std::move(timer), delegate_.get());
@@ -150,26 +83,21 @@
     auth_.reset();
   }
 
-  void ExpectAccessToken(bool use_cached,
-                         mojom::AccessTokenStatus expected_status,
-                         const std::string& expected_token) {
-    base::RunLoop run_loop;
-    auto quit_closure = run_loop.QuitClosure();
-    auth_->GetAccessToken(use_cached, base::BindLambdaForTesting(
-                                          [&](mojom::AccessTokenStatus status,
-                                              const std::string& token) {
-                                            EXPECT_EQ(expected_status, status);
-                                            EXPECT_EQ(expected_token, token);
-                                            std::move(quit_closure).Run();
-                                          }));
-    run_loop.Run();
+  // Helper function for better line wrapping.
+  void RespondWithAccessToken(const std::string& token) {
+    identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+        token, clock_.Now() + kTokenLifetime);
   }
 
-  const CoreAccountId kTestAccountId;
+  // Helper function for better line wrapping.
+  void RespondWithAuthError(GoogleServiceAuthError::State error_state) {
+    identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+        GoogleServiceAuthError(error_state));
+  }
+
   base::test::TaskEnvironment task_environment_;
-  MockIdentityAccessor mock_identity_accessor_;
+  signin::IdentityTestEnvironment identity_test_env_;
   base::SimpleTestClock clock_;
-  std::unique_ptr<FakeIdentityService> identity_service_;
 
   std::unique_ptr<AuthDelegateImpl> delegate_;
   std::unique_ptr<DriveFsAuth> auth_;
@@ -180,31 +108,45 @@
 };
 
 TEST_F(DriveFsAuthTest, GetAccessToken_Success) {
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token", GoogleServiceAuthError::NONE)));
-  ExpectAccessToken(false, mojom::AccessTokenStatus::kSuccess, "auth token");
+  base::RunLoop run_loop;
+  auth_->GetAccessToken(
+      false, base::BindLambdaForTesting([&](mojom::AccessTokenStatus status,
+                                            const std::string& token) {
+        EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+        EXPECT_EQ("auth token", token);
+        run_loop.Quit();
+      }));
+  RespondWithAccessToken("auth token");
+  run_loop.Run();
 }
 
 TEST_F(DriveFsAuthTest, GetAccessToken_GetAccessTokenFailure_Permanent) {
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(std::make_pair(
-          base::nullopt, GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)));
-  ExpectAccessToken(false, mojom::AccessTokenStatus::kAuthError, "");
+  base::RunLoop run_loop;
+  auth_->GetAccessToken(
+      false, base::BindLambdaForTesting([&](mojom::AccessTokenStatus status,
+                                            const std::string& token) {
+        EXPECT_EQ(mojom::AccessTokenStatus::kAuthError, status);
+        EXPECT_TRUE(token.empty());
+        run_loop.Quit();
+      }));
+  RespondWithAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+  run_loop.Run();
 }
 
 TEST_F(DriveFsAuthTest, GetAccessToken_GetAccessTokenFailure_Transient) {
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(std::make_pair(
-          base::nullopt, GoogleServiceAuthError::SERVICE_UNAVAILABLE)));
-  ExpectAccessToken(false, mojom::AccessTokenStatus::kTransientError, "");
+  base::RunLoop run_loop;
+  auth_->GetAccessToken(
+      false, base::BindLambdaForTesting([&](mojom::AccessTokenStatus status,
+                                            const std::string& token) {
+        EXPECT_EQ(mojom::AccessTokenStatus::kTransientError, status);
+        EXPECT_TRUE(token.empty());
+        run_loop.Quit();
+      }));
+  RespondWithAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
+  run_loop.Run();
 }
 
 TEST_F(DriveFsAuthTest, GetAccessToken_GetAccessTokenFailure_Timeout) {
-  identity_service_->set_auth_enabled(false);
   base::RunLoop run_loop;
   auto quit_closure = run_loop.QuitClosure();
   auth_->GetAccessToken(
@@ -213,16 +155,13 @@
                    EXPECT_EQ(mojom::AccessTokenStatus::kAuthError, status);
                    std::move(quit_closure).Run();
                  }));
+  // Timer fires before access token becomes available.
   timer_->Fire();
   run_loop.Run();
 }
 
 TEST_F(DriveFsAuthTest, GetAccessToken_ParallelRequests) {
   base::RunLoop run_loop;
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token", GoogleServiceAuthError::NONE)));
   auto quit_closure = run_loop.QuitClosure();
   auth_->GetAccessToken(
       false, base::BindLambdaForTesting([&](mojom::AccessTokenStatus status,
@@ -237,69 +176,103 @@
         EXPECT_EQ(mojom::AccessTokenStatus::kTransientError, status);
         EXPECT_TRUE(token.empty());
       }));
+  RespondWithAccessToken("auth token");
   run_loop.Run();
 }
 
 TEST_F(DriveFsAuthTest, GetAccessToken_SequentialRequests) {
   for (int i = 0; i < 3; ++i) {
-    EXPECT_CALL(mock_identity_accessor_,
-                GetAccessToken(kTestAccountId, _, "drivefs"))
-        .WillOnce(testing::Return(
-            std::make_pair("auth token", GoogleServiceAuthError::NONE)));
-    ExpectAccessToken(false, mojom::AccessTokenStatus::kSuccess, "auth token");
+    base::RunLoop run_loop;
+    auth_->GetAccessToken(
+        false, base::BindLambdaForTesting([&](mojom::AccessTokenStatus status,
+                                              const std::string& token) {
+          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+          EXPECT_EQ("auth token", token);
+          run_loop.Quit();
+        }));
+    RespondWithAccessToken("auth token");
+    run_loop.Run();
   }
   for (int i = 0; i < 3; ++i) {
-    EXPECT_CALL(mock_identity_accessor_,
-                GetAccessToken(kTestAccountId, _, "drivefs"))
-        .WillOnce(testing::Return(std::make_pair(
-            base::nullopt, GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)));
-    ExpectAccessToken(false, mojom::AccessTokenStatus::kAuthError, "");
+    base::RunLoop run_loop;
+    auth_->GetAccessToken(
+        false, base::BindLambdaForTesting([&](mojom::AccessTokenStatus status,
+                                              const std::string& token) {
+          EXPECT_EQ(mojom::AccessTokenStatus::kAuthError, status);
+          EXPECT_TRUE(token.empty());
+          run_loop.Quit();
+        }));
+    RespondWithAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+    run_loop.Run();
   }
 }
 
 TEST_F(DriveFsAuthTest, Caching) {
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token", GoogleServiceAuthError::NONE)));
-
-  ExpectAccessToken(true, mojom::AccessTokenStatus::kSuccess, "auth token");
+  auth_->GetAccessToken(true, base::BindOnce([](mojom::AccessTokenStatus status,
+                                                const std::string& token) {
+                          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                          EXPECT_EQ("auth token", token);
+                        }));
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
+  RespondWithAccessToken("auth token");
 
   // Second attempt should reuse already available token.
-  ExpectAccessToken(true, mojom::AccessTokenStatus::kSuccess, "auth token");
+  auth_->GetAccessToken(true, base::BindOnce([](mojom::AccessTokenStatus status,
+                                                const std::string& token) {
+                          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                          EXPECT_EQ("auth token", token);
+                        }));
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 }
 
 TEST_F(DriveFsAuthTest, CachedAndNotCached) {
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token", GoogleServiceAuthError::NONE)))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token 2", GoogleServiceAuthError::NONE)));
-
-  ExpectAccessToken(true, mojom::AccessTokenStatus::kSuccess, "auth token");
+  auth_->GetAccessToken(true, base::BindOnce([](mojom::AccessTokenStatus status,
+                                                const std::string& token) {
+                          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                          EXPECT_EQ("auth token", token);
+                        }));
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
+  RespondWithAccessToken("auth token");
 
   // Second attempt should reuse already available token.
-  ExpectAccessToken(true, mojom::AccessTokenStatus::kSuccess, "auth token");
+  auth_->GetAccessToken(true, base::BindOnce([](mojom::AccessTokenStatus status,
+                                                const std::string& token) {
+                          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                          EXPECT_EQ("auth token", token);
+                        }));
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 
   // Now ask for token explicitly bypassing the cache.
-  ExpectAccessToken(false, mojom::AccessTokenStatus::kSuccess, "auth token 2");
+  auth_->GetAccessToken(
+      false, base::BindOnce(
+                 [](mojom::AccessTokenStatus status, const std::string& token) {
+                   EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                   EXPECT_EQ("auth token 2", token);
+                 }));
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
+  RespondWithAccessToken("auth token 2");
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 }
 
 TEST_F(DriveFsAuthTest, CacheExpired) {
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(kTestAccountId, _, "drivefs"))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token", GoogleServiceAuthError::NONE)))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token 2", GoogleServiceAuthError::NONE)));
-
-  ExpectAccessToken(true, mojom::AccessTokenStatus::kSuccess, "auth token");
+  auth_->GetAccessToken(true, base::BindOnce([](mojom::AccessTokenStatus status,
+                                                const std::string& token) {
+                          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                          EXPECT_EQ("auth token", token);
+                        }));
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
+  RespondWithAccessToken("auth token");
 
   clock_.Advance(base::TimeDelta::FromHours(2));
 
-  // As the token expired second mount attempt go to identity.
-  ExpectAccessToken(true, mojom::AccessTokenStatus::kSuccess, "auth token 2");
+  // The token expired so a new one is requested.
+  auth_->GetAccessToken(true, base::BindOnce([](mojom::AccessTokenStatus status,
+                                                const std::string& token) {
+                          EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+                          EXPECT_EQ("auth token 2", token);
+                        }));
+  RespondWithAccessToken("auth token 2");
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 }
 
 }  // namespace
diff --git a/chromeos/components/drivefs/drivefs_host_unittest.cc b/chromeos/components/drivefs/drivefs_host_unittest.cc
index a2b42c5..bcd0102 100644
--- a/chromeos/components/drivefs/drivefs_host_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_host_unittest.cc
@@ -28,14 +28,14 @@
 #include "components/drive/drive_notification_manager.h"
 #include "components/drive/drive_notification_observer.h"
 #include "components/invalidation/impl/fake_invalidation_service.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "mojo/public/cpp/bindings/clone_traits.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "services/identity/public/mojom/identity_accessor.mojom-test-utils.h"
-#include "services/identity/public/mojom/identity_service.mojom.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/test/test_network_connection_tracker.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -46,6 +46,8 @@
 using testing::_;
 using MountFailure = DriveFsHost::MountObserver::MountFailure;
 
+constexpr base::TimeDelta kTokenLifetime = base::TimeDelta::FromHours(1);
+
 class MockDriveFs : public mojom::DriveFsInterceptorForTesting,
                     public mojom::SearchQuery {
  public:
@@ -95,9 +97,9 @@
 class TestingDriveFsHostDelegate : public DriveFsHost::Delegate,
                                    public DriveFsHost::MountObserver {
  public:
-  TestingDriveFsHostDelegate(identity::mojom::IdentityService* identity_service,
+  TestingDriveFsHostDelegate(signin::IdentityManager* identity_manager,
                              const AccountId& account_id)
-      : identity_service_(identity_service),
+      : identity_manager_(identity_manager),
         account_id_(account_id),
         drive_notification_manager_(&invalidation_service_) {}
 
@@ -126,10 +128,8 @@
       override {
     return nullptr;
   }
-  void BindIdentityAccessor(
-      mojo::PendingReceiver<identity::mojom::IdentityAccessor> receiver)
-      override {
-    identity_service_->BindIdentityAccessor(std::move(receiver));
+  signin::IdentityManager* GetIdentityManager() override {
+    return identity_manager_;
   }
   const AccountId& GetAccountId() override { return account_id_; }
   std::string GetObfuscatedAccountId() override {
@@ -151,7 +151,7 @@
     return base::FilePath("/MyFiles");
   }
 
-  identity::mojom::IdentityService* const identity_service_;
+  signin::IdentityManager* const identity_manager_;
   const AccountId account_id_;
   mojo::PendingRemote<mojom::DriveFsBootstrap> pending_bootstrap_;
   invalidation::FakeInvalidationService invalidation_service_;
@@ -160,91 +160,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestingDriveFsHostDelegate);
 };
 
-class MockIdentityAccessor {
- public:
-  explicit MockIdentityAccessor(const base::Clock* clock) : clock_(clock) {}
-  MOCK_METHOD3(
-      GetAccessToken,
-      std::pair<base::Optional<std::string>, GoogleServiceAuthError::State>(
-          const CoreAccountId& account_id,
-          const ::identity::ScopeSet& scopes,
-          const std::string& consumer_id));
-
-  void OnGetAccessToken(
-      const CoreAccountId& account_id,
-      const ::identity::ScopeSet& scopes,
-      const std::string& consumer_id,
-      identity::mojom::IdentityAccessor::GetAccessTokenCallback callback) {
-    if (pause_requests_) {
-      callbacks_.push_back(std::move(callback));
-      return;
-    }
-    auto result = GetAccessToken(account_id, scopes, consumer_id);
-    std::move(callback).Run(std::move(result.first),
-                            clock_->Now() + base::TimeDelta::FromHours(1),
-                            GoogleServiceAuthError(result.second));
-  }
-
-  std::vector<identity::mojom::IdentityAccessor::GetAccessTokenCallback>&
-  callbacks() {
-    return callbacks_;
-  }
-
-  void set_pause_requests(bool pause) { pause_requests_ = pause; }
-
-  const base::Clock* const clock_;
-  bool pause_requests_ = false;
-  std::vector<identity::mojom::IdentityAccessor::GetAccessTokenCallback>
-      callbacks_;
-  mojo::ReceiverSet<identity::mojom::IdentityAccessor>* receivers_ = nullptr;
-};
-
-class FakeIdentityService
-    : public identity::mojom::IdentityAccessorInterceptorForTesting,
-      public identity::mojom::IdentityService {
- public:
-  explicit FakeIdentityService(MockIdentityAccessor* mock) : mock_(mock) {
-    mock_->receivers_ = &receivers_;
-  }
-
-  ~FakeIdentityService() override { mock_->receivers_ = nullptr; }
-
- private:
-  // identity::mojom::IdentityService:
-  void BindIdentityAccessor(
-      mojo::PendingReceiver<identity::mojom::IdentityAccessor> receiver)
-      override {
-    receivers_.Add(this, std::move(receiver));
-  }
-
-  // identity::mojom::IdentityAccessorInterceptorForTesting overrides:
-  void GetUnconsentedPrimaryAccountWhenAvailable(
-      GetUnconsentedPrimaryAccountWhenAvailableCallback callback) override {
-    auto account_id = AccountId::FromUserEmailGaiaId("test@example.com", "ID");
-    std::move(callback).Run(CoreAccountId(account_id.GetUserEmail()),
-                            account_id.GetGaiaId(), account_id.GetUserEmail(),
-                            {});
-  }
-
-  void GetAccessToken(const CoreAccountId& account_id,
-                      const ::identity::ScopeSet& scopes,
-                      const std::string& consumer_id,
-                      GetAccessTokenCallback callback) override {
-    mock_->OnGetAccessToken(account_id, scopes, consumer_id,
-                            std::move(callback));
-  }
-
-  IdentityAccessor* GetForwardingInterface() override {
-    NOTREACHED();
-    return nullptr;
-  }
-
-  MockIdentityAccessor* const mock_;
-  mojo::ReceiverSet<identity::mojom::IdentityAccessor> receivers_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeIdentityService);
-};
-
 class MockDriveFsHostObserver : public DriveFsHostObserver {
  public:
   MOCK_METHOD0(OnUnmounted, void());
@@ -262,8 +177,7 @@
  public:
   DriveFsHostTest()
       : network_connection_tracker_(
-            network::TestNetworkConnectionTracker::CreateInstance()),
-        mock_identity_accessor_(&clock_) {
+            network::TestNetworkConnectionTracker::CreateInstance()) {
     clock_.SetNow(base::Time::Now());
   }
 
@@ -274,10 +188,10 @@
     account_id_ = AccountId::FromUserEmailGaiaId("test@example.com", "ID");
 
     disk_manager_ = std::make_unique<chromeos::disks::MockDiskMountManager>();
-    identity_service_ =
-        std::make_unique<FakeIdentityService>(&mock_identity_accessor_);
+    identity_test_env_.MakeUnconsentedPrimaryAccountAvailable(
+        "test@example.com");
     host_delegate_ = std::make_unique<TestingDriveFsHostDelegate>(
-        identity_service_.get(), account_id_);
+        identity_test_env_.identity_manager(), account_id_);
     auto timer = std::make_unique<base::MockOneShotTimer>();
     timer_ = timer.get();
     host_ = std::make_unique<DriveFsHost>(
@@ -377,21 +291,6 @@
     testing::Mock::VerifyAndClearExpectations(host_delegate_.get());
   }
 
-  void ExpectAccessToken(mojom::AccessTokenStatus expected_status,
-                         const std::string& expected_token) {
-    base::RunLoop run_loop;
-    auto quit_closure = run_loop.QuitClosure();
-    delegate_->GetAccessToken(
-        "client ID", "app ID", {"scope1", "scope2"},
-        base::BindLambdaForTesting(
-            [&](mojom::AccessTokenStatus status, const std::string& token) {
-              EXPECT_EQ(expected_status, status);
-              EXPECT_EQ(expected_token, token);
-              std::move(quit_closure).Run();
-            }));
-    run_loop.Run();
-  }
-
   void Init(mojom::DriveFsConfigurationPtr config,
             mojo::PendingReceiver<mojom::DriveFs> drive_fs_receiver,
             mojo::PendingRemote<mojom::DriveFsDelegate> delegate) override {
@@ -410,8 +309,7 @@
   std::unique_ptr<network::TestNetworkConnectionTracker>
       network_connection_tracker_;
   base::SimpleTestClock clock_;
-  MockIdentityAccessor mock_identity_accessor_;
-  std::unique_ptr<FakeIdentityService> identity_service_;
+  signin::IdentityTestEnvironment identity_test_env_;
   std::unique_ptr<TestingDriveFsHostDelegate> host_delegate_;
   std::unique_ptr<DriveFsHost> host_;
   base::MockOneShotTimer* timer_;
@@ -522,7 +420,7 @@
   };
   for (auto& account : unsupported_accounts) {
     host_delegate_ = std::make_unique<TestingDriveFsHostDelegate>(
-        identity_service_.get(), account);
+        identity_test_env_.identity_manager(), account);
     host_ = std::make_unique<DriveFsHost>(
         profile_path_, host_delegate_.get(), host_delegate_.get(),
         network_connection_tracker_.get(), &clock_, disk_manager_.get(),
@@ -535,25 +433,17 @@
 TEST_F(DriveFsHostTest, GetAccessToken_UnmountDuringMojoRequest) {
   ASSERT_NO_FATAL_FAILURE(DoMount());
 
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(CoreAccountId("test@example.com"), _, "drivefs"))
-      .WillOnce(testing::DoAll(
-          testing::InvokeWithoutArgs([&]() { host_->Unmount(); }),
-          testing::Return(std::make_pair(
-              base::nullopt,
-              GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS))));
-
   base::RunLoop run_loop;
   delegate_.set_disconnect_handler(run_loop.QuitClosure());
   delegate_->GetAccessToken(
       "client ID", "app ID", {"scope1", "scope2"},
       base::BindLambdaForTesting([](mojom::AccessTokenStatus status,
                                     const std::string& token) { FAIL(); }));
+  host_->Unmount();
   run_loop.Run();
   EXPECT_FALSE(host_->IsMounted());
 
-  // Wait for the response to reach the remote if it's still open.
-  mock_identity_accessor_.receivers_->FlushForTesting();
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 }
 
 ACTION_P(CloneStruct, output) {
@@ -713,14 +603,21 @@
 TEST_F(DriveFsHostTest, Remount_CachedOnceOnly) {
   ASSERT_NO_FATAL_FAILURE(DoMount());
 
-  EXPECT_CALL(mock_identity_accessor_,
-              GetAccessToken(CoreAccountId("test@example.com"), _, "drivefs"))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token", GoogleServiceAuthError::NONE)))
-      .WillOnce(testing::Return(
-          std::make_pair("auth token 2", GoogleServiceAuthError::NONE)));
+  // Request an access token.
+  delegate_->GetAccessToken(
+      "client ID", "app ID", {"scope1", "scope2"},
+      base::BindLambdaForTesting(
+          [&](mojom::AccessTokenStatus status, const std::string& token) {
+            EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+            EXPECT_EQ("auth token", token);
+          }));
+  delegate_.FlushForTesting();
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
 
-  ExpectAccessToken(mojom::AccessTokenStatus::kSuccess, "auth token");
+  // Fulfill the request.
+  identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      "auth token", clock_.Now() + kTokenLifetime);
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 
   base::Optional<base::TimeDelta> delay = base::TimeDelta::FromSeconds(5);
   EXPECT_CALL(*host_delegate_, OnUnmounted(delay));
@@ -730,15 +627,28 @@
 
   // Second mount attempt should reuse already available token.
   ASSERT_NO_FATAL_FAILURE(DoMount());
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
   EXPECT_EQ("auth token", init_access_token_.value_or(""));
 
-  // But if it asks for token it goes straight to identity.
-  ExpectAccessToken(mojom::AccessTokenStatus::kSuccess, "auth token 2");
+  // But if it asks for token again it goes to identity manager.
+  delegate_->GetAccessToken(
+      "client ID", "app ID", {"scope1", "scope2"},
+      base::BindLambdaForTesting(
+          [&](mojom::AccessTokenStatus status, const std::string& token) {
+            EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+            EXPECT_EQ("auth token 2", token);
+          }));
+  delegate_.FlushForTesting();
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
+
+  // Fulfill the request with a different token.
+  identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      "auth token 2", clock_.Now() + kTokenLifetime);
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 }
 
 TEST_F(DriveFsHostTest, Remount_RequestInflight) {
   ASSERT_NO_FATAL_FAILURE(DoMount());
-  mock_identity_accessor_.set_pause_requests(true);
 
   delegate_->GetAccessToken(
       "client ID", "app ID", {"scope1", "scope2"},
@@ -750,22 +660,20 @@
   SendOnUnmounted(delay);
   base::RunLoop().RunUntilIdle();
   ASSERT_NO_FATAL_FAILURE(DoUnmount());
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
 
   // Now the response is ready.
-  ASSERT_EQ(1u, mock_identity_accessor_.callbacks().size());
-  std::move(mock_identity_accessor_.callbacks().front())
-      .Run("auth token", clock_.Now() + base::TimeDelta::FromHours(1),
-           GoogleServiceAuthError(GoogleServiceAuthError::NONE));
-  mock_identity_accessor_.receivers_->FlushForTesting();
+  identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      "auth token", clock_.Now() + kTokenLifetime);
 
   // Second mount will reuse previous token.
   ASSERT_NO_FATAL_FAILURE(DoMount());
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
   EXPECT_EQ("auth token", init_access_token_.value_or(""));
 }
 
 TEST_F(DriveFsHostTest, Remount_RequestInflightCompleteAfterMount) {
   ASSERT_NO_FATAL_FAILURE(DoMount());
-  mock_identity_accessor_.set_pause_requests(true);
 
   delegate_->GetAccessToken(
       "client ID", "app ID", {"scope1", "scope2"},
@@ -777,20 +685,28 @@
   SendOnUnmounted(delay);
   base::RunLoop().RunUntilIdle();
   ASSERT_NO_FATAL_FAILURE(DoUnmount());
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
 
   // Second mount will reuse previous token.
   ASSERT_NO_FATAL_FAILURE(DoMount());
   EXPECT_FALSE(init_access_token_);
+  EXPECT_TRUE(identity_test_env_.IsAccessTokenRequestPending());
 
   // Now the response is ready.
-  ASSERT_EQ(1u, mock_identity_accessor_.callbacks().size());
-  std::move(mock_identity_accessor_.callbacks().front())
-      .Run("auth token", clock_.Now() + base::TimeDelta::FromHours(1),
-           GoogleServiceAuthError(GoogleServiceAuthError::NONE));
-  mock_identity_accessor_.receivers_->FlushForTesting();
+  identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      "auth token", clock_.Now() + kTokenLifetime);
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 
   // A new request will reuse the cached token.
-  ExpectAccessToken(mojom::AccessTokenStatus::kSuccess, "auth token");
+  delegate_->GetAccessToken(
+      "client ID", "app ID", {"scope1", "scope2"},
+      base::BindLambdaForTesting(
+          [&](mojom::AccessTokenStatus status, const std::string& token) {
+            EXPECT_EQ(mojom::AccessTokenStatus::kSuccess, status);
+            EXPECT_EQ("auth token", token);
+          }));
+  delegate_.FlushForTesting();
+  EXPECT_FALSE(identity_test_env_.IsAccessTokenRequestPending());
 }
 
 }  // namespace
diff --git a/chromeos/components/drivefs/fake_drivefs.cc b/chromeos/components/drivefs/fake_drivefs.cc
index 4286c4b..5f67d9e 100644
--- a/chromeos/components/drivefs/fake_drivefs.cc
+++ b/chromeos/components/drivefs/fake_drivefs.cc
@@ -27,6 +27,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "net/base/mime_util.h"
+#include "url/gurl.h"
 
 namespace drivefs {
 namespace {
diff --git a/chromeos/components/help_app_ui/BUILD.gn b/chromeos/components/help_app_ui/BUILD.gn
index 73e4745..d63c604 100644
--- a/chromeos/components/help_app_ui/BUILD.gn
+++ b/chromeos/components/help_app_ui/BUILD.gn
@@ -10,13 +10,13 @@
 
 static_library("help_app_ui") {
   sources = [
-    "help_app_guest_ui.cc",
-    "help_app_guest_ui.h",
     "help_app_page_handler.cc",
     "help_app_page_handler.h",
     "help_app_ui.cc",
     "help_app_ui.h",
     "help_app_ui_delegate.h",
+    "help_app_untrusted_ui.cc",
+    "help_app_untrusted_ui.h",
     "url_constants.cc",
     "url_constants.h",
   ]
@@ -29,6 +29,7 @@
     "//chromeos/resources:help_app_resources",
     "//chromeos/system",
     "//content/public/browser",
+    "//content/public/common",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/platform",
     "//ui/resources:webui_resources_grd_grit",
diff --git a/chromeos/components/help_app_ui/DEPS b/chromeos/components/help_app_ui/DEPS
index 8b2618ea..f1b0167 100644
--- a/chromeos/components/help_app_ui/DEPS
+++ b/chromeos/components/help_app_ui/DEPS
@@ -2,6 +2,7 @@
   # Do not add chrome here (use a delegate instead).
   "+chromeos/grit/chromeos_help_app_resources.h",
   "+content/public/browser",
+  "+content/public/common",
   "+ui/resources/grit/webui_resources.h",
   "+ui/webui",
 ]
diff --git a/chromeos/components/help_app_ui/help_app_guest_ui.h b/chromeos/components/help_app_ui/help_app_guest_ui.h
deleted file mode 100644
index 828065a..0000000
--- a/chromeos/components/help_app_ui/help_app_guest_ui.h
+++ /dev/null
@@ -1,17 +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 CHROMEOS_COMPONENTS_HELP_APP_UI_HELP_APP_GUEST_UI_H_
-#define CHROMEOS_COMPONENTS_HELP_APP_UI_HELP_APP_GUEST_UI_H_
-
-namespace content {
-class WebUIDataSource;
-}
-
-namespace chromeos {
-// The data source creation for chrome://help-app-guest.
-content::WebUIDataSource* CreateHelpAppGuestDataSource();
-}  // namespace chromeos
-
-#endif  // CHROMEOS_COMPONENTS_HELP_APP_UI_HELP_APP_GUEST_UI_H_
diff --git a/chromeos/components/help_app_ui/help_app_ui.cc b/chromeos/components/help_app_ui/help_app_ui.cc
index e0ecfde..49d751e 100644
--- a/chromeos/components/help_app_ui/help_app_ui.cc
+++ b/chromeos/components/help_app_ui/help_app_ui.cc
@@ -6,13 +6,14 @@
 
 #include <utility>
 
-#include "chromeos/components/help_app_ui/help_app_guest_ui.h"
 #include "chromeos/components/help_app_ui/help_app_page_handler.h"
+#include "chromeos/components/help_app_ui/help_app_untrusted_ui.h"
 #include "chromeos/components/help_app_ui/url_constants.h"
 #include "chromeos/grit/chromeos_help_app_resources.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/url_constants.h"
 
 namespace chromeos {
 
@@ -41,12 +42,17 @@
       web_ui->GetWebContents()->GetBrowserContext();
   content::WebUIDataSource* host_source = CreateHostDataSource();
   content::WebUIDataSource::Add(browser_context, host_source);
-  // We need a CSP override to use the guest origin in the host.
-  std::string csp = std::string("frame-src ") + kChromeUIHelpAppGuestURL + ";";
+  // We need a CSP override to use the chrome-untrusted:// scheme in the host.
+  std::string csp =
+      std::string("frame-src ") + kChromeUIHelpAppUntrustedURL + ";";
   host_source->OverrideContentSecurityPolicyChildSrc(csp);
 
-  content::WebUIDataSource* guest_source = CreateHelpAppGuestDataSource();
-  content::WebUIDataSource::Add(browser_context, guest_source);
+  content::WebUIDataSource* untrusted_source =
+      CreateHelpAppUntrustedDataSource();
+  content::WebUIDataSource::Add(browser_context, untrusted_source);
+
+  // Add ability to request chrome-untrusted: URLs.
+  web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
 }
 
 HelpAppUI::~HelpAppUI() = default;
diff --git a/chromeos/components/help_app_ui/help_app_guest_ui.cc b/chromeos/components/help_app_ui/help_app_untrusted_ui.cc
similarity index 85%
rename from chromeos/components/help_app_ui/help_app_guest_ui.cc
rename to chromeos/components/help_app_ui/help_app_untrusted_ui.cc
index 9e5381a..df2afb0 100644
--- a/chromeos/components/help_app_ui/help_app_guest_ui.cc
+++ b/chromeos/components/help_app_ui/help_app_untrusted_ui.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/components/help_app_ui/help_app_guest_ui.h"
+#include "chromeos/components/help_app_ui/help_app_untrusted_ui.h"
 
 #include "base/system/sys_info.h"
 #include "chromeos/components/help_app_ui/url_constants.h"
@@ -16,9 +16,9 @@
 namespace chromeos {
 
 // static
-content::WebUIDataSource* CreateHelpAppGuestDataSource() {
+content::WebUIDataSource* CreateHelpAppUntrustedDataSource() {
   content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIHelpAppGuestHost);
+      content::WebUIDataSource::Create(kChromeUIHelpAppUntrustedURL);
   source->AddResourcePath("app.html", IDR_HELP_APP_APP_HTML);
   source->AddResourcePath("app_bin.js", IDR_HELP_APP_APP_BIN_JS);
   source->AddResourcePath("load_time_data.js", IDR_WEBUI_JS_LOAD_TIME_DATA);
@@ -40,8 +40,7 @@
   source->AddString("customizationId", customization_id);
   source->UseStringsJs();
 
-  // TODO(crbug.com/1023700): Better solution before launch.
-  source->DisableDenyXFrameOptions();
+  source->AddFrameAncestor(GURL(kChromeUIHelpAppURL));
   return source;
 }
 
diff --git a/chromeos/components/help_app_ui/help_app_untrusted_ui.h b/chromeos/components/help_app_ui/help_app_untrusted_ui.h
new file mode 100644
index 0000000..6310d2e
--- /dev/null
+++ b/chromeos/components/help_app_ui/help_app_untrusted_ui.h
@@ -0,0 +1,17 @@
+// 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 CHROMEOS_COMPONENTS_HELP_APP_UI_HELP_APP_UNTRUSTED_UI_H_
+#define CHROMEOS_COMPONENTS_HELP_APP_UI_HELP_APP_UNTRUSTED_UI_H_
+
+namespace content {
+class WebUIDataSource;
+}
+
+namespace chromeos {
+// The data source creation for chrome-untrusted://help-app.
+content::WebUIDataSource* CreateHelpAppUntrustedDataSource();
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_HELP_APP_UI_HELP_APP_UNTRUSTED_UI_H_
diff --git a/chromeos/components/help_app_ui/resources/index.html b/chromeos/components/help_app_ui/resources/index.html
index b61b823..ed1528d 100644
--- a/chromeos/components/help_app_ui/resources/index.html
+++ b/chromeos/components/help_app_ui/resources/index.html
@@ -23,4 +23,4 @@
 <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
 <script src="/help_app.mojom-lite.js"></script>
 <script src="/browser_proxy.js"></script>
-<iframe src="chrome://help-app-guest/app.html"></iframe>
+<iframe src="chrome-untrusted://help-app/app.html"></iframe>
diff --git a/chromeos/components/help_app_ui/test/help_app_ui_browsertest.js b/chromeos/components/help_app_ui/test/help_app_ui_browsertest.js
index 7f841f7..64bcabd1 100644
--- a/chromeos/components/help_app_ui/test/help_app_ui_browsertest.js
+++ b/chromeos/components/help_app_ui/test/help_app_ui_browsertest.js
@@ -9,7 +9,7 @@
 GEN('#include "chromeos/constants/chromeos_features.h"');
 
 const HOST_ORIGIN = 'chrome://help-app';
-const GUEST_ORIGIN = 'chrome://help-app-guest';
+const GUEST_ORIGIN = 'chrome-untrusted://help-app';
 
 var HelpAppUIBrowserTest = class extends testing.Test {
   /** @override */
diff --git a/chromeos/components/help_app_ui/url_constants.cc b/chromeos/components/help_app_ui/url_constants.cc
index cf5f948..0794c0c 100644
--- a/chromeos/components/help_app_ui/url_constants.cc
+++ b/chromeos/components/help_app_ui/url_constants.cc
@@ -8,7 +8,6 @@
 
 const char kChromeUIHelpAppHost[] = "help-app";
 const char kChromeUIHelpAppURL[] = "chrome://help-app/";
-const char kChromeUIHelpAppGuestHost[] = "help-app-guest";
-const char kChromeUIHelpAppGuestURL[] = "chrome://help-app-guest/";
+const char kChromeUIHelpAppUntrustedURL[] = "chrome-untrusted://help-app/";
 
 }  // namespace chromeos
diff --git a/chromeos/components/help_app_ui/url_constants.h b/chromeos/components/help_app_ui/url_constants.h
index 9426292..766195f 100644
--- a/chromeos/components/help_app_ui/url_constants.h
+++ b/chromeos/components/help_app_ui/url_constants.h
@@ -9,8 +9,7 @@
 
 extern const char kChromeUIHelpAppHost[];
 extern const char kChromeUIHelpAppURL[];
-extern const char kChromeUIHelpAppGuestHost[];
-extern const char kChromeUIHelpAppGuestURL[];
+extern const char kChromeUIHelpAppUntrustedURL[];
 
 }  // namespace chromeos
 
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 59730de..719522e 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -220,7 +220,7 @@
 
 // ChromeOS Files App mounts RAR archives via rar2fs instead of avfs.
 // https://crbug.com/996549
-const base::Feature kRar2Fs{"Rar2Fs", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kRar2Fs{"Rar2Fs", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables or disables Release Notes on Chrome OS.
 const base::Feature kReleaseNotes{"ReleaseNotes",
diff --git a/chromeos/dbus/audio/cras_audio_client.cc b/chromeos/dbus/audio/cras_audio_client.cc
index 4a20b00..4643859 100644
--- a/chromeos/dbus/audio/cras_audio_client.cc
+++ b/chromeos/dbus/audio/cras_audio_client.cc
@@ -325,6 +325,36 @@
                             base::DoNothing());
   }
 
+  void SetPlayerPlaybackStatus(const std::string& playback_status) override {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetPlayerPlaybackStatus);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(playback_status);
+    cras_proxy_->CallMethod(&method_call,
+                            dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                            base::DoNothing());
+  }
+
+  void SetPlayerIdentity(const std::string& identity) override {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetPlayerIdentity);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(identity);
+    cras_proxy_->CallMethod(&method_call,
+                            dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                            base::DoNothing());
+  }
+
+  void SetPlayerPosition(const int64_t& position) override {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetPlayerPosition);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendInt64(position);
+    cras_proxy_->CallMethod(&method_call,
+                            dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                            base::DoNothing());
+  }
+
   void WaitForServiceToBeAvailable(
       WaitForServiceToBeAvailableCallback callback) override {
     cras_proxy_->WaitForServiceToBeAvailable(std::move(callback));
diff --git a/chromeos/dbus/audio/cras_audio_client.h b/chromeos/dbus/audio/cras_audio_client.h
index 73d4522..d4f8cb2 100644
--- a/chromeos/dbus/audio/cras_audio_client.h
+++ b/chromeos/dbus/audio/cras_audio_client.h
@@ -163,6 +163,18 @@
       int32_t channels,
       const std::vector<double>& mixer) = 0;
 
+  // Sets the player playback status. Possible status are "Playing", "Paused" or
+  // "Stopped".
+  virtual void SetPlayerPlaybackStatus(const std::string& playback_status) = 0;
+
+  // Sets the player identity. Identity is a human readable title for the source
+  // of the media player. This could be the name of the app or the name of the
+  // site playing media.
+  virtual void SetPlayerIdentity(const std::string& playback_identity) = 0;
+
+  // Sets the current track position for the player in microseconds
+  virtual void SetPlayerPosition(const int64_t& position) = 0;
+
   // Runs the callback as soon as the service becomes available.
   virtual void WaitForServiceToBeAvailable(
       WaitForServiceToBeAvailableCallback callback) = 0;
diff --git a/chromeos/dbus/audio/cras_audio_client_unittest.cc b/chromeos/dbus/audio/cras_audio_client_unittest.cc
index 37c8f1c..6dfc6ad 100644
--- a/chromeos/dbus/audio/cras_audio_client_unittest.cc
+++ b/chromeos/dbus/audio/cras_audio_client_unittest.cc
@@ -164,6 +164,23 @@
   EXPECT_FALSE(reader->HasMoreData());
 }
 
+// Expect the reader to have a string.
+void ExpectStringArgument(std::string expected_string,
+                          dbus::MessageReader* reader) {
+  std::string value;
+  ASSERT_TRUE(reader->PopString(&value));
+  EXPECT_EQ(expected_string, value);
+  EXPECT_FALSE(reader->HasMoreData());
+}
+
+// Expect the reader to have a int64_t.
+void ExpectInt64Argument(int64_t expected_int64, dbus::MessageReader* reader) {
+  int64_t value;
+  ASSERT_TRUE(reader->PopInt64(&value));
+  EXPECT_EQ(expected_int64, value);
+  EXPECT_FALSE(reader->HasMoreData());
+}
+
 void WriteNodesToResponse(const AudioNodeList& node_list,
                           dbus::MessageWriter* writer) {
   dbus::MessageWriter sub_writer(nullptr);
@@ -1110,4 +1127,52 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(CrasAudioClientTest, SetPlayerPlaybackStatus) {
+  const std::string kStatus = "paused";
+  // Create response.
+  std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
+
+  // Set expectations.
+  PrepareForMethodCall(cras::kSetPlayerPlaybackStatus,
+                       base::BindRepeating(&ExpectStringArgument, kStatus),
+                       response.get());
+
+  // Call method.
+  client()->SetPlayerPlaybackStatus(kStatus);
+  // Run the message loop.
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(CrasAudioClientTest, SetPlayerIdentity) {
+  const std::string kIdentity = "Chrome Player";
+  // Create response.
+  std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
+
+  // Set expectations.
+  PrepareForMethodCall(cras::kSetPlayerIdentity,
+                       base::BindRepeating(&ExpectStringArgument, kIdentity),
+                       response.get());
+
+  // Call method.
+  client()->SetPlayerIdentity(kIdentity);
+  // Run the message loop.
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(CrasAudioClientTest, SetPlayerPosition) {
+  const int64_t kPosition = 2020224;
+  // Create response.
+  std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
+
+  // Set expectations.
+  PrepareForMethodCall(cras::kSetPlayerPosition,
+                       base::BindRepeating(&ExpectInt64Argument, kPosition),
+                       response.get());
+
+  // Call method.
+  client()->SetPlayerPosition(kPosition);
+  // Run the message loop.
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/audio/fake_cras_audio_client.cc b/chromeos/dbus/audio/fake_cras_audio_client.cc
index a2256d17..071bf4f 100644
--- a/chromeos/dbus/audio/fake_cras_audio_client.cc
+++ b/chromeos/dbus/audio/fake_cras_audio_client.cc
@@ -212,6 +212,14 @@
     int32_t channels,
     const std::vector<double>& mixer) {}
 
+void FakeCrasAudioClient::SetPlayerPlaybackStatus(
+    const std::string& playback_status) {}
+
+void FakeCrasAudioClient::SetPlayerIdentity(
+    const std::string& playback_identity) {}
+
+void FakeCrasAudioClient::SetPlayerPosition(const int64_t& position) {}
+
 void FakeCrasAudioClient::AddActiveOutputNode(uint64_t node_id) {
   for (size_t i = 0; i < node_list_.size(); ++i) {
     if (node_list_[i].id == node_id)
diff --git a/chromeos/dbus/audio/fake_cras_audio_client.h b/chromeos/dbus/audio/fake_cras_audio_client.h
index 1a06b9b8..aaff8eeb 100644
--- a/chromeos/dbus/audio/fake_cras_audio_client.h
+++ b/chromeos/dbus/audio/fake_cras_audio_client.h
@@ -51,6 +51,9 @@
   void SwapLeftRight(uint64_t node_id, bool swap) override;
   void SetGlobalOutputChannelRemix(int32_t channels,
                                    const std::vector<double>& mixer) override;
+  void SetPlayerPlaybackStatus(const std::string& playback_status) override;
+  void SetPlayerIdentity(const std::string& playback_identity) override;
+  void SetPlayerPosition(const int64_t& position) override;
   void WaitForServiceToBeAvailable(
       WaitForServiceToBeAvailableCallback callback) override;
 
diff --git a/chromeos/profiles/airmont.afdo.newest.txt b/chromeos/profiles/airmont.afdo.newest.txt
index 40d3cb9..abbb98c 100644
--- a/chromeos/profiles/airmont.afdo.newest.txt
+++ b/chromeos/profiles/airmont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-airmont-82-4044.5-1581936665-benchmark-82.0.4065.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-airmont-82-4044.25-1582540590-benchmark-82.0.4065.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/profiles/broadwell.afdo.newest.txt b/chromeos/profiles/broadwell.afdo.newest.txt
index cf913b2..3386a4ce 100644
--- a/chromeos/profiles/broadwell.afdo.newest.txt
+++ b/chromeos/profiles/broadwell.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-broadwell-82-4028.0-1581935713-benchmark-82.0.4065.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-broadwell-82-4044.15-1582543985-benchmark-82.0.4065.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/profiles/silvermont.afdo.newest.txt b/chromeos/profiles/silvermont.afdo.newest.txt
index 1e55b417..b98007b 100644
--- a/chromeos/profiles/silvermont.afdo.newest.txt
+++ b/chromeos/profiles/silvermont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-silvermont-82-4044.15-1581938780-benchmark-82.0.4065.0-r1-redacted.afdo.xz
\ No newline at end of file
+chromeos-chrome-amd64-silvermont-82-4044.25-1582542147-benchmark-82.0.4065.0-r1-redacted.afdo.xz
\ No newline at end of file
diff --git a/chromeos/tpm/install_attributes.cc b/chromeos/tpm/install_attributes.cc
index 4378542..8e11c27 100644
--- a/chromeos/tpm/install_attributes.cc
+++ b/chromeos/tpm/install_attributes.cc
@@ -191,9 +191,10 @@
       device_locked_ = true;
 
       static const char* const kEnterpriseAttributes[] = {
-          kAttrEnterpriseDeviceId, kAttrEnterpriseDomain,
-          kAttrEnterpriseRealm,    kAttrEnterpriseMode,
-          kAttrEnterpriseUser,     kAttrConsumerKioskEnabled,
+          kAttrEnterpriseDeviceId,   kAttrEnterpriseDomain,
+          kAttrEnterpriseRealm,      kAttrEnterpriseMode,
+          kAttrEnterpriseOwned,      kAttrEnterpriseUser,
+          kAttrConsumerKioskEnabled,
       };
       std::map<std::string, std::string> attr_map;
       for (size_t i = 0; i < base::size(kEnterpriseAttributes); ++i) {
@@ -319,12 +320,16 @@
   }
 
   // Set values in the InstallAttrs.
-  std::string kiosk_enabled;
-  if (device_mode == policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH)
+  std::string kiosk_enabled, enterprise_owned;
+  if (device_mode == policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) {
     kiosk_enabled = "true";
+  } else {
+    enterprise_owned = "true";
+  }
   std::string mode = GetDeviceModeString(device_mode);
   if (!tpm_util::InstallAttributesSet(kAttrConsumerKioskEnabled,
                                       kiosk_enabled) ||
+      !tpm_util::InstallAttributesSet(kAttrEnterpriseOwned, enterprise_owned) ||
       !tpm_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
       !tpm_util::InstallAttributesSet(kAttrEnterpriseDomain, domain) ||
       !tpm_util::InstallAttributesSet(kAttrEnterpriseRealm, realm) ||
@@ -456,6 +461,7 @@
 const char InstallAttributes::kAttrEnterpriseDomain[] = "enterprise.domain";
 const char InstallAttributes::kAttrEnterpriseRealm[] = "enterprise.realm";
 const char InstallAttributes::kAttrEnterpriseMode[] = "enterprise.mode";
+const char InstallAttributes::kAttrEnterpriseOwned[] = "enterprise.owned";
 const char InstallAttributes::kAttrEnterpriseUser[] = "enterprise.user";
 const char InstallAttributes::kAttrConsumerKioskEnabled[] =
     "consumer.app_kiosk_enabled";
@@ -506,10 +512,7 @@
     return policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
   if (mode == InstallAttributes::kDemoDeviceMode)
     return policy::DEVICE_MODE_DEMO;
-  if (mode.empty())
-    return policy::DEVICE_MODE_NOT_SET;
-  NOTREACHED() << "Invalid device mode: " << mode;
-  return policy::DEVICE_MODE_ENTERPRISE;
+  return policy::DEVICE_MODE_NOT_SET;
 }
 
 void InstallAttributes::DecodeInstallAttributes(
@@ -520,6 +523,8 @@
   registration_realm_.clear();
   registration_device_id_.clear();
 
+  const std::string enterprise_owned =
+      ReadMapKey(attr_map, kAttrEnterpriseOwned);
   const std::string consumer_kiosk_enabled =
       ReadMapKey(attr_map, kAttrConsumerKioskEnabled);
   const std::string mode = ReadMapKey(attr_map, kAttrEnterpriseMode);
@@ -528,14 +533,21 @@
   const std::string device_id = ReadMapKey(attr_map, kAttrEnterpriseDeviceId);
   const std::string user_deprecated = ReadMapKey(attr_map, kAttrEnterpriseUser);
 
-  registration_mode_ = GetDeviceModeFromString(mode);
-
-  if (registration_mode_ == policy::DEVICE_MODE_ENTERPRISE ||
-      registration_mode_ == policy::DEVICE_MODE_ENTERPRISE_AD ||
-      registration_mode_ == policy::DEVICE_MODE_DEMO) {
+  if (enterprise_owned == "true") {
     WarnIfNonempty(attr_map, kAttrConsumerKioskEnabled);
     registration_device_id_ = device_id;
 
+    // Set registration_mode_.
+    registration_mode_ = GetDeviceModeFromString(mode);
+    if (registration_mode_ != policy::DEVICE_MODE_ENTERPRISE &&
+        registration_mode_ != policy::DEVICE_MODE_ENTERPRISE_AD &&
+        registration_mode_ != policy::DEVICE_MODE_DEMO) {
+      if (!mode.empty()) {
+        LOG(WARNING) << "Bad " << kAttrEnterpriseMode << ": " << mode;
+      }
+      registration_mode_ = policy::DEVICE_MODE_ENTERPRISE;
+    }
+
     if (registration_mode_ == policy::DEVICE_MODE_ENTERPRISE ||
         registration_mode_ == policy::DEVICE_MODE_DEMO) {
       // Either set registration_domain_ ...
@@ -562,6 +574,7 @@
     return;
   }
 
+  WarnIfNonempty(attr_map, kAttrEnterpriseOwned);
   WarnIfNonempty(attr_map, kAttrEnterpriseDomain);
   WarnIfNonempty(attr_map, kAttrEnterpriseRealm);
   WarnIfNonempty(attr_map, kAttrEnterpriseDeviceId);
diff --git a/chromeos/tpm/install_attributes_unittest.cc b/chromeos/tpm/install_attributes_unittest.cc
index 2652723..86819bf 100644
--- a/chromeos/tpm/install_attributes_unittest.cc
+++ b/chromeos/tpm/install_attributes_unittest.cc
@@ -264,9 +264,8 @@
   install_attributes_->Init(GetTempPath());
   EXPECT_EQ(policy::DEVICE_MODE_PENDING, install_attributes_->GetMode());
   // Lock the attributes as if it was done from older Chrome version.
-  ASSERT_TRUE(
-      tpm_util::InstallAttributesSet(InstallAttributes::kAttrEnterpriseMode,
-                                     InstallAttributes::kEnterpriseDeviceMode));
+  ASSERT_TRUE(tpm_util::InstallAttributesSet(
+      InstallAttributes::kAttrEnterpriseOwned, "true"));
   ASSERT_TRUE(tpm_util::InstallAttributesSet(
       InstallAttributes::kAttrEnterpriseUser, kTestUserDeprecated));
   ASSERT_TRUE(tpm_util::InstallAttributesFinalize());
@@ -283,8 +282,8 @@
 
 TEST_F(InstallAttributesTest, Init) {
   cryptohome::SerializedInstallAttributes install_attrs_proto;
-  SetAttribute(&install_attrs_proto, InstallAttributes::kAttrEnterpriseMode,
-               InstallAttributes::kEnterpriseDeviceMode);
+  SetAttribute(&install_attrs_proto, InstallAttributes::kAttrEnterpriseOwned,
+               "true");
   SetAttribute(&install_attrs_proto, InstallAttributes::kAttrEnterpriseUser,
                kTestUserDeprecated);
   const std::string blob(install_attrs_proto.SerializeAsString());
@@ -321,9 +320,8 @@
   EXPECT_EQ(policy::DEVICE_MODE_PENDING, install_attributes_->GetMode());
 
   // Write test values.
-  ASSERT_TRUE(
-      tpm_util::InstallAttributesSet(InstallAttributes::kAttrEnterpriseMode,
-                                     InstallAttributes::kEnterpriseDeviceMode));
+  ASSERT_TRUE(tpm_util::InstallAttributesSet(
+      InstallAttributes::kAttrEnterpriseOwned, "true"));
   ASSERT_TRUE(tpm_util::InstallAttributesSet(
       InstallAttributes::kAttrEnterpriseUser, kTestUserDeprecated));
   ASSERT_TRUE(tpm_util::InstallAttributesFinalize());
diff --git a/components/arc/session/arc_session_impl.cc b/components/arc/session/arc_session_impl.cc
index 27b09c1..14fbb1c1 100644
--- a/components/arc/session/arc_session_impl.cc
+++ b/components/arc/session/arc_session_impl.cc
@@ -182,8 +182,8 @@
 
 void ArcSessionDelegateImpl::GetFreeDiskSpace(
     GetFreeDiskSpaceCallback callback) {
-  PostTaskAndReplyWithResult(
-      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()},
       base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
                      base::FilePath("/home")),
       std::move(callback));
diff --git a/components/dom_distiller/core/viewer.cc b/components/dom_distiller/core/viewer.cc
index 70ec76d..02e8dc4 100644
--- a/components/dom_distiller/core/viewer.cc
+++ b/components/dom_distiller/core/viewer.cc
@@ -175,7 +175,13 @@
 }
 
 const std::string GetSetTitleJs(std::string title) {
+#if defined(OS_ANDROID)
   base::Value value(title);
+#else  // !defined(OS_ANDROID)
+  std::string suffix(
+      l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_TITLE_SUFFIX));
+  base::Value value(title + " - " + suffix);
+#endif
   std::string output;
   base::JSONWriter::Write(value, &output);
   return "setTitle(" + output + ");";
diff --git a/components/dom_distiller_strings.grdp b/components/dom_distiller_strings.grdp
index 1198c87..aca9e594 100644
--- a/components/dom_distiller_strings.grdp
+++ b/components/dom_distiller_strings.grdp
@@ -31,9 +31,18 @@
   <message name="IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT" desc="The text to show in place of reading list article content if the article is not found.">
     Could not find the requested article.
   </message>
-  <message name="IDS_DOM_DISTILLER_VIEWER_LOADING_TITLE" desc="The text to show in place of a reading list article title while the article is loading. Translation should match TC ID 7558334641404735182, 7078777000119799848, and 8486137854427127199.">
-    Simplified view
-  </message>
+  <if expr="is_android">
+    <then>
+      <message name="IDS_DOM_DISTILLER_VIEWER_LOADING_TITLE" desc="The text to show in place of a reading list article title while the article is loading. Translation should match TC ID 7558334641404735182, 7078777000119799848, and 8486137854427127199.">
+        Simplified view
+      </message>
+    </then>
+    <else>
+      <message name="IDS_DOM_DISTILLER_VIEWER_LOADING_TITLE" desc="The text to show in place of a reading list article title while the article is loading.">
+        Loading...
+      </message>
+    </else>
+  </if>
   <message name="IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT" desc="The text to show in place of reading list article content if there is no data found.">
     No data found.
   </message>
@@ -49,5 +58,8 @@
   <message name="IDS_DOM_DISTILLER_WEBUI_TITLE" desc="The title to show on the DOM Distiller debug page.">
     DOM Distiller
   </message>
+  <message name="IDS_DOM_DISTILLER_VIEWER_TITLE_SUFFIX" desc="The suffix to show after the page title to indicate we are in reader mode. For example, if the page title was 'An Article', this would be appended to create the title 'An Article - Reader Mode'.">
+    Reader Mode
+  </message>
 
 </grit-part>
diff --git a/components/dom_distiller_strings_grdp/IDS_DOM_DISTILLER_VIEWER_TITLE_SUFFIX.png.sha1 b/components/dom_distiller_strings_grdp/IDS_DOM_DISTILLER_VIEWER_TITLE_SUFFIX.png.sha1
new file mode 100644
index 0000000..5608a51
--- /dev/null
+++ b/components/dom_distiller_strings_grdp/IDS_DOM_DISTILLER_VIEWER_TITLE_SUFFIX.png.sha1
@@ -0,0 +1 @@
+f049a5162a611e94ae4e6912dd941393972ced8a
\ No newline at end of file
diff --git a/components/feed/core/proto/ui/action/ui_feed_action.proto b/components/feed/core/proto/ui/action/ui_feed_action.proto
index 681fbc2..12f7c9c 100644
--- a/components/feed/core/proto/ui/action/ui_feed_action.proto
+++ b/components/feed/core/proto/ui/action/ui_feed_action.proto
@@ -105,6 +105,10 @@
   // opening the url. Once this finishes, the client will attach to the url its
   //  latest frequency token as the value of this query param.
   optional string consistency_token_query_param_name = 2;
+  // The content ID that was interacted with to cause a URL open.
+  optional components.feed.core.proto.wire.ContentId content_id = 3;
+  // Roundtripped server data on a per-action level.
+  optional components.feed.core.proto.wire.ActionPayload payload = 4;
 }
 
 // Data needed by Stream to open a context menu.
diff --git a/components/feed/core/proto/ui/piet/accessibility.proto b/components/feed/core/proto/ui/piet/accessibility.proto
index b92fb90..b73760b 100644
--- a/components/feed/core/proto/ui/piet/accessibility.proto
+++ b/components/feed/core/proto/ui/piet/accessibility.proto
@@ -43,6 +43,19 @@
     // ID coming from a template.
     ParameterizedTextBindingRef accessibility_id_binding = 5;
   }
+
+  oneof context_data {
+    // A string that may be spoken by the system that describes the result of an
+    // action. For example, "Opens the article." This provides additional
+    // context over the description.
+
+    // NOTE: Only supported by iOS and maps to accessibilityHint on an
+    // accessible element.
+    ParameterizedText context = 6;
+
+    // In case this is coming from a template.
+    ParameterizedTextBindingRef context_binding = 7;
+  }
 }
 
 // Semantic roles played by a UI element related to accessibility.
diff --git a/components/feed/core/proto/wire/capability.proto b/components/feed/core/proto/wire/capability.proto
index 5686b70..48ac07c 100644
--- a/components/feed/core/proto/wire/capability.proto
+++ b/components/feed/core/proto/wire/capability.proto
@@ -12,7 +12,7 @@
 option java_outer_classname = "CapabilityProto";
 
 // Feature capability of either the client or the server.
-// Next ID: 13.
+// Next ID: 14.
 enum Capability {
   UNKNOWN_CAPABILITY = 0;
   BASE_UI = 1;
@@ -24,8 +24,8 @@
   ARTICLE_SNIPPETS = 8;
   CAROUSELS = 9;
   ELEMENTS = 10;
-  CONTENT_ID_UNIFICATION = 11;
   SEND_FEEDBACK = 12;
+  CLICK_ACTION = 13;
 
-  reserved 3;
+  reserved 3, 11;
 }
diff --git a/components/module_installer/android/java/src/org/chromium/components/module_installer/util/Timer.java b/components/module_installer/android/java/src/org/chromium/components/module_installer/util/Timer.java
index 73b7544..1078a077 100644
--- a/components/module_installer/android/java/src/org/chromium/components/module_installer/util/Timer.java
+++ b/components/module_installer/android/java/src/org/chromium/components/module_installer/util/Timer.java
@@ -6,7 +6,7 @@
 
 import android.os.SystemClock;
 
-import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample;
+import org.chromium.base.metrics.RecordHistogram;
 
 import java.io.Closeable;
 
@@ -38,8 +38,6 @@
     }
 
     public static void recordStartupTime() {
-        String name = "Android.FeatureModules.StartupTime";
-        TimesHistogramSample sample = new TimesHistogramSample(name);
-        sample.record(sTotalTime);
+        RecordHistogram.recordTimesHistogram("Android.FeatureModules.StartupTime", sTotalTime);
     }
 }
diff --git a/components/omnibox/browser/omnibox_pedal_concepts.h b/components/omnibox/browser/omnibox_pedal_concepts.h
index 383a017e..d6fac090 100644
--- a/components/omnibox/browser/omnibox_pedal_concepts.h
+++ b/components/omnibox/browser/omnibox_pedal_concepts.h
@@ -10,7 +10,7 @@
 // This value is generated during Pedal concept data processing, and written
 // to all data files as well as the source code here to ensure synchrony.
 // The runtime loaded data must match this version exactly or it won't load.
-constexpr int OMNIBOX_PEDAL_CONCEPTS_DATA_VERSION = 15150030;
+constexpr int OMNIBOX_PEDAL_CONCEPTS_DATA_VERSION = 15220441;
 
 // Unique identifiers for Pedals, used to bind loaded data to implementations.
 enum class OmniboxPedalId {
diff --git a/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc b/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc
index a0202c5..feb87e2 100644
--- a/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc
+++ b/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc
@@ -785,9 +785,11 @@
       // MANAGE_PASSWORDS
       {
           "browser change passwords",
+          "browser edit passwords",
           "browser manage passwords",
           "browser manager passwords",
           "browser passwords change",
+          "browser passwords edit",
           "browser passwords manage",
           "browser passwords manager",
           "browser passwords update",
@@ -800,17 +802,28 @@
           "change passwords chrome",
           "change passwords google chrome",
           "chrome change passwords",
+          "chrome edit passwords",
           "chrome manage passwords",
           "chrome manager passwords",
           "chrome passwords change",
+          "chrome passwords edit",
           "chrome passwords manage",
           "chrome passwords manager",
           "chrome passwords update",
           "chrome update passwords",
+          "edit browser passwords",
+          "edit chrome passwords",
+          "edit google chrome passwords",
+          "edit passwords",
+          "edit passwords browser",
+          "edit passwords chrome",
+          "edit passwords google chrome",
           "google chrome change passwords",
+          "google chrome edit passwords",
           "google chrome manage passwords",
           "google chrome manager passwords",
           "google chrome passwords change",
+          "google chrome passwords edit",
           "google chrome passwords manage",
           "google chrome passwords manager",
           "google chrome passwords update",
@@ -830,6 +843,7 @@
           "manager passwords chrome",
           "manager passwords google chrome",
           "passwords browser change",
+          "passwords browser edit",
           "passwords browser manage",
           "passwords browser manager",
           "passwords browser update",
@@ -838,10 +852,16 @@
           "passwords change chrome",
           "passwords change google chrome",
           "passwords chrome change",
+          "passwords chrome edit",
           "passwords chrome manage",
           "passwords chrome manager",
           "passwords chrome update",
+          "passwords edit",
+          "passwords edit browser",
+          "passwords edit chrome",
+          "passwords edit google chrome",
           "passwords google chrome change",
+          "passwords google chrome edit",
           "passwords google chrome manage",
           "passwords google chrome manager",
           "passwords google chrome update",
@@ -868,24 +888,50 @@
 
       // CHANGE_HOME_PAGE
       {
+          "browser change home",
+          "browser change home button",
           "browser change home page",
           "browser change homepage",
+          "browser choose home",
+          "browser choose home button",
           "browser choose home page",
           "browser choose homepage",
+          "browser home button change",
+          "browser home button choose",
+          "browser home button set",
+          "browser home change",
+          "browser home choose",
           "browser home page change",
           "browser home page choose",
           "browser home page set",
+          "browser home set",
           "browser homepage change",
           "browser homepage choose",
           "browser homepage set",
+          "browser set home",
+          "browser set home button",
           "browser set home page",
           "browser set homepage",
+          "change browser home",
+          "change browser home button",
           "change browser home page",
           "change browser homepage",
+          "change chrome home",
+          "change chrome home button",
           "change chrome home page",
           "change chrome homepage",
+          "change google chrome home",
+          "change google chrome home button",
           "change google chrome home page",
           "change google chrome homepage",
+          "change home",
+          "change home browser",
+          "change home button",
+          "change home button browser",
+          "change home button chrome",
+          "change home button google chrome",
+          "change home chrome",
+          "change home google chrome",
           "change home page",
           "change home page browser",
           "change home page chrome",
@@ -894,12 +940,26 @@
           "change homepage browser",
           "change homepage chrome",
           "change homepage google chrome",
+          "choose browser home",
+          "choose browser home button",
           "choose browser home page",
           "choose browser homepage",
+          "choose chrome home",
+          "choose chrome home button",
           "choose chrome home page",
           "choose chrome homepage",
+          "choose google chrome home",
+          "choose google chrome home button",
           "choose google chrome home page",
           "choose google chrome homepage",
+          "choose home",
+          "choose home browser",
+          "choose home button",
+          "choose home button browser",
+          "choose home button chrome",
+          "choose home button google chrome",
+          "choose home chrome",
+          "choose home google chrome",
           "choose home page",
           "choose home page browser",
           "choose home page chrome",
@@ -908,30 +968,92 @@
           "choose homepage browser",
           "choose homepage chrome",
           "choose homepage google chrome",
+          "chrome change home",
+          "chrome change home button",
           "chrome change home page",
           "chrome change homepage",
+          "chrome choose home",
+          "chrome choose home button",
           "chrome choose home page",
           "chrome choose homepage",
+          "chrome home button change",
+          "chrome home button choose",
+          "chrome home button set",
+          "chrome home change",
+          "chrome home choose",
           "chrome home page change",
           "chrome home page choose",
           "chrome home page set",
+          "chrome home set",
           "chrome homepage change",
           "chrome homepage choose",
           "chrome homepage set",
+          "chrome set home",
+          "chrome set home button",
           "chrome set home page",
           "chrome set homepage",
+          "google chrome change home",
+          "google chrome change home button",
           "google chrome change home page",
           "google chrome change homepage",
+          "google chrome choose home",
+          "google chrome choose home button",
           "google chrome choose home page",
           "google chrome choose homepage",
+          "google chrome home button change",
+          "google chrome home button choose",
+          "google chrome home button set",
+          "google chrome home change",
+          "google chrome home choose",
           "google chrome home page change",
           "google chrome home page choose",
           "google chrome home page set",
+          "google chrome home set",
           "google chrome homepage change",
           "google chrome homepage choose",
           "google chrome homepage set",
+          "google chrome set home",
+          "google chrome set home button",
           "google chrome set home page",
           "google chrome set homepage",
+          "home browser change",
+          "home browser choose",
+          "home browser set",
+          "home button browser change",
+          "home button browser choose",
+          "home button browser set",
+          "home button change",
+          "home button change browser",
+          "home button change chrome",
+          "home button change google chrome",
+          "home button choose",
+          "home button choose browser",
+          "home button choose chrome",
+          "home button choose google chrome",
+          "home button chrome change",
+          "home button chrome choose",
+          "home button chrome set",
+          "home button google chrome change",
+          "home button google chrome choose",
+          "home button google chrome set",
+          "home button set",
+          "home button set browser",
+          "home button set chrome",
+          "home button set google chrome",
+          "home change",
+          "home change browser",
+          "home change chrome",
+          "home change google chrome",
+          "home choose",
+          "home choose browser",
+          "home choose chrome",
+          "home choose google chrome",
+          "home chrome change",
+          "home chrome choose",
+          "home chrome set",
+          "home google chrome change",
+          "home google chrome choose",
+          "home google chrome set",
           "home page browser change",
           "home page browser choose",
           "home page browser set",
@@ -953,6 +1075,10 @@
           "home page set browser",
           "home page set chrome",
           "home page set google chrome",
+          "home set",
+          "home set browser",
+          "home set chrome",
+          "home set google chrome",
           "homepage browser change",
           "homepage browser choose",
           "homepage browser set",
@@ -974,12 +1100,26 @@
           "homepage set browser",
           "homepage set chrome",
           "homepage set google chrome",
+          "set browser home",
+          "set browser home button",
           "set browser home page",
           "set browser homepage",
+          "set chrome home",
+          "set chrome home button",
           "set chrome home page",
           "set chrome homepage",
+          "set google chrome home",
+          "set google chrome home button",
           "set google chrome home page",
           "set google chrome homepage",
+          "set home",
+          "set home browser",
+          "set home button",
+          "set home button browser",
+          "set home button chrome",
+          "set home button google chrome",
+          "set home chrome",
+          "set home google chrome",
           "set home page",
           "set home page browser",
           "set home page chrome",
@@ -994,36 +1134,71 @@
       {
           "browser card info change",
           "browser card info edit",
+          "browser card info manage",
           "browser card info update",
           "browser cards change",
           "browser cards edit",
+          "browser cards manage",
           "browser cards update",
           "browser change card info",
           "browser change cards",
           "browser change credit card",
           "browser change credit card info",
           "browser change credit cards",
+          "browser change payment",
+          "browser change payment methods",
+          "browser change payments",
           "browser credit card change",
           "browser credit card edit",
           "browser credit card info change",
           "browser credit card info edit",
+          "browser credit card info manage",
           "browser credit card info update",
+          "browser credit card manage",
           "browser credit card update",
           "browser credit cards change",
           "browser credit cards edit",
+          "browser credit cards manage",
           "browser credit cards update",
           "browser edit card info",
           "browser edit cards",
           "browser edit credit card",
           "browser edit credit card info",
           "browser edit credit cards",
+          "browser edit payment",
+          "browser edit payment methods",
+          "browser edit payments",
+          "browser manage card info",
+          "browser manage cards",
+          "browser manage credit card",
+          "browser manage credit card info",
+          "browser manage credit cards",
+          "browser manage payment",
+          "browser manage payment methods",
+          "browser manage payments",
+          "browser payment change",
+          "browser payment edit",
+          "browser payment manage",
+          "browser payment methods change",
+          "browser payment methods edit",
+          "browser payment methods manage",
+          "browser payment methods update",
+          "browser payment update",
+          "browser payments change",
+          "browser payments edit",
+          "browser payments manage",
+          "browser payments update",
           "browser update card info",
           "browser update cards",
           "browser update credit card",
           "browser update credit card info",
           "browser update credit cards",
+          "browser update payment",
+          "browser update payment methods",
+          "browser update payments",
           "card info browser change",
           "card info browser edit",
+          "card info browser manage",
           "card info browser update",
           "card info change",
           "card info change browser",
@@ -1031,6 +1206,7 @@
           "card info change google chrome",
           "card info chrome change",
           "card info chrome edit",
+          "card info chrome manage",
           "card info chrome update",
           "card info edit",
           "card info edit browser",
@@ -1038,13 +1214,19 @@
           "card info edit google chrome",
           "card info google chrome change",
           "card info google chrome edit",
+          "card info google chrome manage",
           "card info google chrome update",
+          "card info manage",
+          "card info manage browser",
+          "card info manage chrome",
+          "card info manage google chrome",
           "card info update",
           "card info update browser",
           "card info update chrome",
           "card info update google chrome",
           "cards browser change",
           "cards browser edit",
+          "cards browser manage",
           "cards browser update",
           "cards change",
           "cards change browser",
@@ -1052,6 +1234,7 @@
           "cards change google chrome",
           "cards chrome change",
           "cards chrome edit",
+          "cards chrome manage",
           "cards chrome update",
           "cards edit",
           "cards edit browser",
@@ -1059,7 +1242,12 @@
           "cards edit google chrome",
           "cards google chrome change",
           "cards google chrome edit",
+          "cards google chrome manage",
           "cards google chrome update",
+          "cards manage",
+          "cards manage browser",
+          "cards manage chrome",
+          "cards manage google chrome",
           "cards update",
           "cards update browser",
           "cards update chrome",
@@ -1069,6 +1257,9 @@
           "change browser credit card",
           "change browser credit card info",
           "change browser credit cards",
+          "change browser payment",
+          "change browser payment methods",
+          "change browser payments",
           "change card info",
           "change card info browser",
           "change card info chrome",
@@ -1082,6 +1273,9 @@
           "change chrome credit card",
           "change chrome credit card info",
           "change chrome credit cards",
+          "change chrome payment",
+          "change chrome payment methods",
+          "change chrome payments",
           "change credit card",
           "change credit card browser",
           "change credit card chrome",
@@ -1099,38 +1293,88 @@
           "change google chrome credit card",
           "change google chrome credit card info",
           "change google chrome credit cards",
+          "change google chrome payment",
+          "change google chrome payment methods",
+          "change google chrome payments",
+          "change payment",
+          "change payment browser",
+          "change payment chrome",
+          "change payment google chrome",
+          "change payment methods",
+          "change payment methods browser",
+          "change payment methods chrome",
+          "change payment methods google chrome",
+          "change payments",
+          "change payments browser",
+          "change payments chrome",
+          "change payments google chrome",
           "chrome card info change",
           "chrome card info edit",
+          "chrome card info manage",
           "chrome card info update",
           "chrome cards change",
           "chrome cards edit",
+          "chrome cards manage",
           "chrome cards update",
           "chrome change card info",
           "chrome change cards",
           "chrome change credit card",
           "chrome change credit card info",
           "chrome change credit cards",
+          "chrome change payment",
+          "chrome change payment methods",
+          "chrome change payments",
           "chrome credit card change",
           "chrome credit card edit",
           "chrome credit card info change",
           "chrome credit card info edit",
+          "chrome credit card info manage",
           "chrome credit card info update",
+          "chrome credit card manage",
           "chrome credit card update",
           "chrome credit cards change",
           "chrome credit cards edit",
+          "chrome credit cards manage",
           "chrome credit cards update",
           "chrome edit card info",
           "chrome edit cards",
           "chrome edit credit card",
           "chrome edit credit card info",
           "chrome edit credit cards",
+          "chrome edit payment",
+          "chrome edit payment methods",
+          "chrome edit payments",
+          "chrome manage card info",
+          "chrome manage cards",
+          "chrome manage credit card",
+          "chrome manage credit card info",
+          "chrome manage credit cards",
+          "chrome manage payment",
+          "chrome manage payment methods",
+          "chrome manage payments",
+          "chrome payment change",
+          "chrome payment edit",
+          "chrome payment manage",
+          "chrome payment methods change",
+          "chrome payment methods edit",
+          "chrome payment methods manage",
+          "chrome payment methods update",
+          "chrome payment update",
+          "chrome payments change",
+          "chrome payments edit",
+          "chrome payments manage",
+          "chrome payments update",
           "chrome update card info",
           "chrome update cards",
           "chrome update credit card",
           "chrome update credit card info",
           "chrome update credit cards",
+          "chrome update payment",
+          "chrome update payment methods",
+          "chrome update payments",
           "credit card browser change",
           "credit card browser edit",
+          "credit card browser manage",
           "credit card browser update",
           "credit card change",
           "credit card change browser",
@@ -1138,6 +1382,7 @@
           "credit card change google chrome",
           "credit card chrome change",
           "credit card chrome edit",
+          "credit card chrome manage",
           "credit card chrome update",
           "credit card edit",
           "credit card edit browser",
@@ -1145,9 +1390,11 @@
           "credit card edit google chrome",
           "credit card google chrome change",
           "credit card google chrome edit",
+          "credit card google chrome manage",
           "credit card google chrome update",
           "credit card info browser change",
           "credit card info browser edit",
+          "credit card info browser manage",
           "credit card info browser update",
           "credit card info change",
           "credit card info change browser",
@@ -1155,6 +1402,7 @@
           "credit card info change google chrome",
           "credit card info chrome change",
           "credit card info chrome edit",
+          "credit card info chrome manage",
           "credit card info chrome update",
           "credit card info edit",
           "credit card info edit browser",
@@ -1162,17 +1410,27 @@
           "credit card info edit google chrome",
           "credit card info google chrome change",
           "credit card info google chrome edit",
+          "credit card info google chrome manage",
           "credit card info google chrome update",
+          "credit card info manage",
+          "credit card info manage browser",
+          "credit card info manage chrome",
+          "credit card info manage google chrome",
           "credit card info update",
           "credit card info update browser",
           "credit card info update chrome",
           "credit card info update google chrome",
+          "credit card manage",
+          "credit card manage browser",
+          "credit card manage chrome",
+          "credit card manage google chrome",
           "credit card update",
           "credit card update browser",
           "credit card update chrome",
           "credit card update google chrome",
           "credit cards browser change",
           "credit cards browser edit",
+          "credit cards browser manage",
           "credit cards browser update",
           "credit cards change",
           "credit cards change browser",
@@ -1180,6 +1438,7 @@
           "credit cards change google chrome",
           "credit cards chrome change",
           "credit cards chrome edit",
+          "credit cards chrome manage",
           "credit cards chrome update",
           "credit cards edit",
           "credit cards edit browser",
@@ -1187,7 +1446,12 @@
           "credit cards edit google chrome",
           "credit cards google chrome change",
           "credit cards google chrome edit",
+          "credit cards google chrome manage",
           "credit cards google chrome update",
+          "credit cards manage",
+          "credit cards manage browser",
+          "credit cards manage chrome",
+          "credit cards manage google chrome",
           "credit cards update",
           "credit cards update browser",
           "credit cards update chrome",
@@ -1197,6 +1461,9 @@
           "edit browser credit card",
           "edit browser credit card info",
           "edit browser credit cards",
+          "edit browser payment",
+          "edit browser payment methods",
+          "edit browser payments",
           "edit card info",
           "edit card info browser",
           "edit card info chrome",
@@ -1210,6 +1477,9 @@
           "edit chrome credit card",
           "edit chrome credit card info",
           "edit chrome credit cards",
+          "edit chrome payment",
+          "edit chrome payment methods",
+          "edit chrome payments",
           "edit credit card",
           "edit credit card browser",
           "edit credit card chrome",
@@ -1227,41 +1497,233 @@
           "edit google chrome credit card",
           "edit google chrome credit card info",
           "edit google chrome credit cards",
+          "edit google chrome payment",
+          "edit google chrome payment methods",
+          "edit google chrome payments",
+          "edit payment",
+          "edit payment browser",
+          "edit payment chrome",
+          "edit payment google chrome",
+          "edit payment methods",
+          "edit payment methods browser",
+          "edit payment methods chrome",
+          "edit payment methods google chrome",
+          "edit payments",
+          "edit payments browser",
+          "edit payments chrome",
+          "edit payments google chrome",
           "google chrome card info change",
           "google chrome card info edit",
+          "google chrome card info manage",
           "google chrome card info update",
           "google chrome cards change",
           "google chrome cards edit",
+          "google chrome cards manage",
           "google chrome cards update",
           "google chrome change card info",
           "google chrome change cards",
           "google chrome change credit card",
           "google chrome change credit card info",
           "google chrome change credit cards",
+          "google chrome change payment",
+          "google chrome change payment methods",
+          "google chrome change payments",
           "google chrome credit card change",
           "google chrome credit card edit",
           "google chrome credit card info change",
           "google chrome credit card info edit",
+          "google chrome credit card info manage",
           "google chrome credit card info update",
+          "google chrome credit card manage",
           "google chrome credit card update",
           "google chrome credit cards change",
           "google chrome credit cards edit",
+          "google chrome credit cards manage",
           "google chrome credit cards update",
           "google chrome edit card info",
           "google chrome edit cards",
           "google chrome edit credit card",
           "google chrome edit credit card info",
           "google chrome edit credit cards",
+          "google chrome edit payment",
+          "google chrome edit payment methods",
+          "google chrome edit payments",
+          "google chrome manage card info",
+          "google chrome manage cards",
+          "google chrome manage credit card",
+          "google chrome manage credit card info",
+          "google chrome manage credit cards",
+          "google chrome manage payment",
+          "google chrome manage payment methods",
+          "google chrome manage payments",
+          "google chrome payment change",
+          "google chrome payment edit",
+          "google chrome payment manage",
+          "google chrome payment methods change",
+          "google chrome payment methods edit",
+          "google chrome payment methods manage",
+          "google chrome payment methods update",
+          "google chrome payment update",
+          "google chrome payments change",
+          "google chrome payments edit",
+          "google chrome payments manage",
+          "google chrome payments update",
           "google chrome update card info",
           "google chrome update cards",
           "google chrome update credit card",
           "google chrome update credit card info",
           "google chrome update credit cards",
+          "google chrome update payment",
+          "google chrome update payment methods",
+          "google chrome update payments",
+          "manage browser card info",
+          "manage browser cards",
+          "manage browser credit card",
+          "manage browser credit card info",
+          "manage browser credit cards",
+          "manage browser payment",
+          "manage browser payment methods",
+          "manage browser payments",
+          "manage card info",
+          "manage card info browser",
+          "manage card info chrome",
+          "manage card info google chrome",
+          "manage cards",
+          "manage cards browser",
+          "manage cards chrome",
+          "manage cards google chrome",
+          "manage chrome card info",
+          "manage chrome cards",
+          "manage chrome credit card",
+          "manage chrome credit card info",
+          "manage chrome credit cards",
+          "manage chrome payment",
+          "manage chrome payment methods",
+          "manage chrome payments",
+          "manage credit card",
+          "manage credit card browser",
+          "manage credit card chrome",
+          "manage credit card google chrome",
+          "manage credit card info",
+          "manage credit card info browser",
+          "manage credit card info chrome",
+          "manage credit card info google chrome",
+          "manage credit cards",
+          "manage credit cards browser",
+          "manage credit cards chrome",
+          "manage credit cards google chrome",
+          "manage google chrome card info",
+          "manage google chrome cards",
+          "manage google chrome credit card",
+          "manage google chrome credit card info",
+          "manage google chrome credit cards",
+          "manage google chrome payment",
+          "manage google chrome payment methods",
+          "manage google chrome payments",
+          "manage payment",
+          "manage payment browser",
+          "manage payment chrome",
+          "manage payment google chrome",
+          "manage payment methods",
+          "manage payment methods browser",
+          "manage payment methods chrome",
+          "manage payment methods google chrome",
+          "manage payments",
+          "manage payments browser",
+          "manage payments chrome",
+          "manage payments google chrome",
+          "payment browser change",
+          "payment browser edit",
+          "payment browser manage",
+          "payment browser update",
+          "payment change",
+          "payment change browser",
+          "payment change chrome",
+          "payment change google chrome",
+          "payment chrome change",
+          "payment chrome edit",
+          "payment chrome manage",
+          "payment chrome update",
+          "payment edit",
+          "payment edit browser",
+          "payment edit chrome",
+          "payment edit google chrome",
+          "payment google chrome change",
+          "payment google chrome edit",
+          "payment google chrome manage",
+          "payment google chrome update",
+          "payment manage",
+          "payment manage browser",
+          "payment manage chrome",
+          "payment manage google chrome",
+          "payment methods browser change",
+          "payment methods browser edit",
+          "payment methods browser manage",
+          "payment methods browser update",
+          "payment methods change",
+          "payment methods change browser",
+          "payment methods change chrome",
+          "payment methods change google chrome",
+          "payment methods chrome change",
+          "payment methods chrome edit",
+          "payment methods chrome manage",
+          "payment methods chrome update",
+          "payment methods edit",
+          "payment methods edit browser",
+          "payment methods edit chrome",
+          "payment methods edit google chrome",
+          "payment methods google chrome change",
+          "payment methods google chrome edit",
+          "payment methods google chrome manage",
+          "payment methods google chrome update",
+          "payment methods manage",
+          "payment methods manage browser",
+          "payment methods manage chrome",
+          "payment methods manage google chrome",
+          "payment methods update",
+          "payment methods update browser",
+          "payment methods update chrome",
+          "payment methods update google chrome",
+          "payment update",
+          "payment update browser",
+          "payment update chrome",
+          "payment update google chrome",
+          "payments browser change",
+          "payments browser edit",
+          "payments browser manage",
+          "payments browser update",
+          "payments change",
+          "payments change browser",
+          "payments change chrome",
+          "payments change google chrome",
+          "payments chrome change",
+          "payments chrome edit",
+          "payments chrome manage",
+          "payments chrome update",
+          "payments edit",
+          "payments edit browser",
+          "payments edit chrome",
+          "payments edit google chrome",
+          "payments google chrome change",
+          "payments google chrome edit",
+          "payments google chrome manage",
+          "payments google chrome update",
+          "payments manage",
+          "payments manage browser",
+          "payments manage chrome",
+          "payments manage google chrome",
+          "payments update",
+          "payments update browser",
+          "payments update chrome",
+          "payments update google chrome",
           "update browser card info",
           "update browser cards",
           "update browser credit card",
           "update browser credit card info",
           "update browser credit cards",
+          "update browser payment",
+          "update browser payment methods",
+          "update browser payments",
           "update card info",
           "update card info browser",
           "update card info chrome",
@@ -1275,6 +1737,9 @@
           "update chrome credit card",
           "update chrome credit card info",
           "update chrome credit cards",
+          "update chrome payment",
+          "update chrome payment methods",
+          "update chrome payments",
           "update credit card",
           "update credit card browser",
           "update credit card chrome",
@@ -1292,6 +1757,21 @@
           "update google chrome credit card",
           "update google chrome credit card info",
           "update google chrome credit cards",
+          "update google chrome payment",
+          "update google chrome payment methods",
+          "update google chrome payments",
+          "update payment",
+          "update payment browser",
+          "update payment chrome",
+          "update payment google chrome",
+          "update payment methods",
+          "update payment methods browser",
+          "update payment methods chrome",
+          "update payment methods google chrome",
+          "update payments",
+          "update payments browser",
+          "update payments chrome",
+          "update payments google chrome",
       },
 
       // LAUNCH_INCOGNITO
diff --git a/components/omnibox/resources/omnibox_pedal_concepts.json b/components/omnibox/resources/omnibox_pedal_concepts.json
index 7a23172..deb06ce 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedals_translation_model",
   "schema_version": 1,
-  "time_generated": "20200106T192754",
+  "time_generated": "20200224T180007",
   "primary_language_code": "en",
   "locales": [
     {
@@ -420,6 +420,7 @@
               "required": true,
               "single": true,
               "synonyms": [
+                "edit",
                 "manager",
                 "manage",
                 "update",
@@ -461,7 +462,9 @@
               "single": true,
               "synonyms": [
                 "home page",
-                "homepage"
+                "homepage",
+                "home",
+                "home button"
               ]
             }
           ]
@@ -482,6 +485,7 @@
               "required": true,
               "single": true,
               "synonyms": [
+                "manage",
                 "update",
                 "edit",
                 "change"
@@ -495,7 +499,10 @@
                 "credit cards",
                 "credit card",
                 "card info",
-                "cards"
+                "cards",
+                "payment",
+                "payments",
+                "payment methods"
               ]
             }
           ]
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_de.json b/components/omnibox/resources/omnibox_pedal_concepts_de.json
index e12f9b25..d6c441c 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_de.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_de.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 1,
-  "data_version": 15150030,
+  "data_version": 15220441,
   "tokenize_characters": " -",
   "dictionary": [
     "aktualisieren",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_en.json b/components/omnibox/resources/omnibox_pedal_concepts_en.json
index 248308d6..ff1aed31 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_en.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_en.json
@@ -1,13 +1,14 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 1,
-  "data_version": 15150030,
+  "data_version": 15220441,
   "tokenize_characters": " -",
   "dictionary": [
     "a",
     "an",
     "browser",
     "browsing",
+    "button",
     "cache",
     "card",
     "cards",
@@ -41,12 +42,15 @@
     "launch",
     "manage",
     "manager",
+    "methods",
     "mode",
     "my",
     "on",
     "open",
     "page",
     "passwords",
+    "payment",
+    "payments",
     "private",
     "remove",
     "search",
@@ -76,8 +80,8 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               3
@@ -86,28 +90,7 @@
               2
             ],
             [
-              9
-            ]
-          ]
-        },
-        {
-          "required": true,
-          "single": true,
-          "synonyms": [
-            [
-              15
-            ],
-            [
-              44
-            ],
-            [
-              20
-            ],
-            [
               10
-            ],
-            [
-              59
             ]
           ]
         },
@@ -116,13 +99,34 @@
           "single": true,
           "synonyms": [
             [
-              23
+              16
             ],
             [
-              4
+              48
             ],
             [
-              13
+              21
+            ],
+            [
+              11
+            ],
+            [
+              63
+            ]
+          ]
+        },
+        {
+          "required": true,
+          "single": true,
+          "synonyms": [
+            [
+              24
+            ],
+            [
+              5
+            ],
+            [
+              14
             ]
           ]
         }
@@ -137,14 +141,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -153,16 +157,16 @@
           "single": true,
           "synonyms": [
             [
+              9
+            ],
+            [
               8
             ],
             [
-              7
+              54
             ],
             [
               50
-            ],
-            [
-              46
             ]
           ]
         },
@@ -171,21 +175,21 @@
           "single": true,
           "synonyms": [
             [
-              48,
-              45,
-              18
+              52,
+              49,
+              19
             ],
             [
-              14,
-              45,
-              18
+              15,
+              49,
+              19
             ],
             [
-              45,
-              18
+              49,
+              19
             ],
             [
-              45
+              49
             ]
           ]
         }
@@ -200,14 +204,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -216,16 +220,19 @@
           "single": true,
           "synonyms": [
             [
+              37
+            ],
+            [
               36
             ],
             [
-              35
+              60
             ],
             [
-              56
+              8
             ],
             [
-              7
+              18
             ]
           ]
         },
@@ -234,7 +241,7 @@
           "single": true,
           "synonyms": [
             [
-              42
+              44
             ]
           ]
         }
@@ -249,14 +256,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -265,13 +272,13 @@
           "single": true,
           "synonyms": [
             [
-              7
-            ],
-            [
               8
             ],
             [
-              47
+              9
+            ],
+            [
+              51
             ]
           ]
         },
@@ -280,8 +287,15 @@
           "single": true,
           "synonyms": [
             [
-              24,
-              41
+              25,
+              4
+            ],
+            [
+              25,
+              43
+            ],
+            [
+              26
             ],
             [
               25
@@ -299,14 +313,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -315,39 +329,52 @@
           "single": true,
           "synonyms": [
             [
-              56
+              36
             ],
             [
+              60
+            ],
+            [
+              8
+            ],
+            [
+              18
+            ]
+          ]
+        },
+        {
+          "required": true,
+          "single": true,
+          "synonyms": [
+            [
+              13,
+              6,
+              31
+            ],
+            [
+              45,
+              38
+            ],
+            [
+              13,
               7
             ],
             [
-              17
-            ]
-          ]
-        },
-        {
-          "required": true,
-          "single": true,
-          "synonyms": [
-            [
-              12,
-              5,
-              30
-            ],
-            [
-              12,
+              13,
               6
             ],
             [
-              12,
-              5
+              6,
+              31
             ],
             [
-              5,
-              30
+              46
             ],
             [
-              6
+              45
+            ],
+            [
+              7
             ]
           ]
         }
@@ -362,14 +389,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -378,19 +405,19 @@
           "single": true,
           "synonyms": [
             [
-              34
+              35
             ],
             [
-              11
+              12
             ],
             [
-              49
+              53
             ],
             [
-              19
+              20
             ],
             [
-              40
+              42
             ]
           ]
         },
@@ -399,31 +426,31 @@
           "single": true,
           "synonyms": [
             [
-              29,
-              58
+              30,
+              62
             ],
             [
-              29,
-              37
+              30,
+              39
             ],
             [
-              43,
-              58
+              47,
+              62
             ],
             [
-              29,
-              51
+              30,
+              55
             ],
             [
-              43,
-              37
+              47,
+              39
             ],
             [
-              43,
-              51
+              47,
+              55
             ],
             [
-              29
+              30
             ]
           ]
         }
@@ -438,14 +465,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -454,11 +481,11 @@
           "single": true,
           "synonyms": [
             [
-              7,
-              33
+              8,
+              34
             ],
             [
-              55
+              59
             ]
           ]
         },
@@ -467,14 +494,14 @@
           "single": true,
           "synonyms": [
             [
-              53,
-              41
+              57,
+              43
             ],
             [
-              41
+              43
             ],
             [
-              53
+              57
             ]
           ]
         }
@@ -489,14 +516,14 @@
           "single": true,
           "synonyms": [
             [
-              22,
-              9
+              23,
+              10
             ],
             [
               2
             ],
             [
-              9
+              10
             ]
           ]
         },
@@ -505,13 +532,13 @@
           "single": true,
           "synonyms": [
             [
-              57
+              61
             ],
             [
-              32
+              33
             ],
             [
-              56
+              60
             ]
           ]
         }
@@ -523,43 +550,43 @@
     "single": false,
     "synonyms": [
       [
-        31
+        32
       ],
       [
-        60
+        64
       ],
       [
-        21
+        22
       ],
       [
-        26
+        27
       ],
       [
-        52
+        56
       ],
       [
         1
       ],
       [
-        16
+        17
       ],
       [
-        28
+        29
       ],
       [
-        38
+        40
       ],
       [
-        39
+        41
       ],
       [
-        54
+        58
       ],
       [
         0
       ],
       [
-        27
+        28
       ]
     ]
   },
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_fr.json b/components/omnibox/resources/omnibox_pedal_concepts_fr.json
index d5cb982..11014d9a 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_fr.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_fr.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 1,
-  "data_version": 15150030,
+  "data_version": 15220441,
   "tokenize_characters": " -",
   "dictionary": [
     "accueil",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_ja.json b/components/omnibox/resources/omnibox_pedal_concepts_ja.json
index 6a135c1..cc7d794 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_ja.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_ja.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 1,
-  "data_version": 15150030,
+  "data_version": 15220441,
   "tokenize_characters": "",
   "dictionary": [
     " ",
diff --git a/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json b/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json
index db8e9c7..29fb68d 100644
--- a/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json
+++ b/components/omnibox/resources/omnibox_pedal_concepts_zh-CN.json
@@ -1,7 +1,7 @@
 {
   "schema": "pedal_concepts_runtime",
   "schema_version": 1,
-  "data_version": 15150030,
+  "data_version": 15220441,
   "tokenize_characters": "",
   "dictionary": [
     " ",
diff --git a/components/password_manager/core/browser/leak_detection/BUILD.gn b/components/password_manager/core/browser/leak_detection/BUILD.gn
index 929426d..47a62fe 100644
--- a/components/password_manager/core/browser/leak_detection/BUILD.gn
+++ b/components/password_manager/core/browser/leak_detection/BUILD.gn
@@ -67,6 +67,8 @@
     "mock_leak_detection_check_factory.h",
     "mock_leak_detection_delegate.cc",
     "mock_leak_detection_delegate.h",
+    "mock_leak_detection_request_factory.cc",
+    "mock_leak_detection_request_factory.h",
   ]
   deps = [
     ":leak_detection",
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc b/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
index d83f936..621a4b7 100644
--- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
@@ -13,6 +13,7 @@
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
 #include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h"
 #include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "crypto/sha2.h"
@@ -39,16 +40,6 @@
 const int64_t kMockElapsedTime =
     base::ScopedMockElapsedTimersForTest::kMockElapsedTime.InMilliseconds();
 
-class MockLeakDetectionRequest : public LeakDetectionRequestInterface {
- public:
-  // LeakDetectionRequestInterface:
-  MOCK_METHOD(void, LookupSingleLeak,
-              (network::mojom::URLLoaderFactory*,
-               const std::string&,
-               LookupSingleLeakPayload,
-               LookupSingleLeakCallback), (override));
-};
-
 struct TestLeakDetectionRequest : public LeakDetectionRequestInterface {
   ~TestLeakDetectionRequest() override = default;
   // LeakDetectionRequestInterface:
@@ -64,13 +55,6 @@
   LookupSingleLeakCallback callback_;
 };
 
-class MockLeakDetectionRequestFactory : public LeakDetectionRequestFactory {
- public:
-  // LeakDetectionRequestFactory:
-  MOCK_CONST_METHOD0(CreateNetworkRequest,
-                     std::unique_ptr<LeakDetectionRequestInterface>());
-};
-
 // Helper struct for making a fake network request.
 struct PayloadAndCallback {
   std::string payload;
diff --git a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
index 9687345e..fcbe6f0 100644
--- a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
+++ b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
@@ -12,6 +12,7 @@
 #include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
 #include "components/signin/public/identity_manager/access_token_fetcher.h"
 #include "components/signin/public/identity_manager/access_token_info.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -27,7 +28,7 @@
                          [weak_holder](const auto& element) {
                            return element.get() == weak_holder;
                          });
-  DCHECK(it != queue->end());
+  CHECK(it != queue->end());
   std::unique_ptr<BulkLeakCheckImpl::CredentialHolder> holder = std::move(*it);
   queue->erase(it);
   return holder;
@@ -51,6 +52,9 @@
 
   // Request for the needed access token.
   std::unique_ptr<signin::AccessTokenFetcher> token_fetcher;
+
+  // Network request for the API call.
+  std::unique_ptr<LeakDetectionRequestInterface> network_request_;
 };
 
 LeakCheckCredential::LeakCheckCredential(base::string16 username,
@@ -138,7 +142,25 @@
     // |this| can be destroyed here.
     return;
   }
-  // TODO(crbug.com/1049185): make a network request.
+
+  holder->token_fetcher.reset();
+  holder->network_request_ = network_request_factory_->CreateNetworkRequest();
+  holder->network_request_->LookupSingleLeak(
+      url_loader_factory_.get(), access_token_info.token,
+      std::move(holder->payload),
+      base::BindOnce(&BulkLeakCheckImpl::OnLookupLeakResponse,
+                     weak_ptr_factory_.GetWeakPtr(), holder.get()));
+  waiting_response_.push_back(std::move(holder));
+}
+
+void BulkLeakCheckImpl::OnLookupLeakResponse(
+    CredentialHolder* weak_holder,
+    std::unique_ptr<SingleLookupResponse> response) {
+  std::unique_ptr<CredentialHolder> holder =
+      RemoveFromQueue(weak_holder, &waiting_response_);
+
+  holder->network_request_.reset();
+  // TODO(crbug.com/1049185): decrypt the stuff.
 }
 
 }  // namespace password_manager
\ No newline at end of file
diff --git a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
index 79459e3..83903c1 100644
--- a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
+++ b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
 
 namespace network {
@@ -25,6 +26,7 @@
 namespace password_manager {
 
 class BulkLeakCheckDelegateInterface;
+struct SingleLookupResponse;
 
 // Implementation of the bulk leak check.
 // Every credential in the list is processed consequitively:
@@ -48,6 +50,13 @@
   void CheckCredentials(std::vector<LeakCheckCredential> credentials) override;
   size_t GetPendingChecksCount() const override;
 
+#if defined(UNIT_TEST)
+  void set_network_factory(
+      std::unique_ptr<LeakDetectionRequestFactory> factory) {
+    network_request_factory_ = std::move(factory);
+  }
+#endif  // defined(UNIT_TEST)
+
  private:
   // Called when a payload for one credential is ready.
   void OnPayloadReady(CredentialHolder* weak_holder,
@@ -58,6 +67,10 @@
                     GoogleServiceAuthError error,
                     signin::AccessTokenInfo access_token_info);
 
+  // Called when the server replied with something.
+  void OnLookupLeakResponse(CredentialHolder* weak_holder,
+                            std::unique_ptr<SingleLookupResponse> response);
+
   // Delegate for the instance. Should outlive |this|.
   BulkLeakCheckDelegateInterface* const delegate_;
 
@@ -68,6 +81,10 @@
   // endpoint.
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
+  // A factory for creating network requests.
+  std::unique_ptr<LeakDetectionRequestFactory> network_request_factory_ =
+      std::make_unique<LeakDetectionRequestFactory>();
+
   // The key used to encrypt/decrypt all the payloads for all the credentials.
   // Creating it once saves CPU time.
   const std::string encryption_key_;
@@ -81,6 +98,9 @@
   // the background thread.
   base::circular_deque<std::unique_ptr<CredentialHolder>> waiting_token_;
 
+  // The queue of the requests waiting for the server reply.
+  base::circular_deque<std::unique_ptr<CredentialHolder>> waiting_response_;
+
   // Task runner for preparing the payload. It takes a lot of memory. Therefore,
   // those tasks aren't parallelized.
   scoped_refptr<base::SequencedTaskRunner> payload_task_runner_;
diff --git a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc
index e188c05..67c417f6 100644
--- a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/test/task_environment.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
 #include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "services/network/test/test_shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -16,6 +17,14 @@
 namespace password_manager {
 namespace {
 
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::ByMove;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::Return;
+
+constexpr char kAccessToken[] = "access_token";
 constexpr char kTestEmail[] = "user@gmail.com";
 
 LeakCheckCredential TestCredential(base::StringPiece username) {
@@ -29,7 +38,12 @@
       : bulk_check_(
             &delegate_,
             identity_test_env_.identity_manager(),
-            base::MakeRefCounted<network::TestSharedURLLoaderFactory>()) {}
+            base::MakeRefCounted<network::TestSharedURLLoaderFactory>()) {
+    auto mock_request_factory = std::make_unique<
+        ::testing::StrictMock<MockLeakDetectionRequestFactory>>();
+    request_factory_ = mock_request_factory.get();
+    bulk_check_.set_network_factory(std::move(mock_request_factory));
+  }
 
   void RunUntilIdle() { task_env_.RunUntilIdle(); }
 
@@ -37,12 +51,16 @@
     return identity_test_env_;
   }
   MockBulkLeakCheckDelegateInterface& delegate() { return delegate_; }
+  MockLeakDetectionRequestFactory* request_factory() {
+    return request_factory_;
+  }
   BulkLeakCheckImpl& bulk_check() { return bulk_check_; }
 
  private:
   base::test::TaskEnvironment task_env_;
   signin::IdentityTestEnvironment identity_test_env_;
   ::testing::StrictMock<MockBulkLeakCheckDelegateInterface> delegate_;
+  MockLeakDetectionRequestFactory* request_factory_;
   BulkLeakCheckImpl bulk_check_;
 };
 
@@ -81,7 +99,6 @@
   identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
   identity_test_env().SetRefreshTokenForAccount(info.account_id);
 
-  EXPECT_CALL(delegate(), OnFinishedCredential).Times(0);
   EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure));
 
   std::vector<LeakCheckCredential> credentials;
@@ -98,7 +115,6 @@
   identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
   identity_test_env().SetRefreshTokenForAccount(info.account_id);
 
-  EXPECT_CALL(delegate(), OnFinishedCredential).Times(0);
   EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNetworkError));
 
   std::vector<LeakCheckCredential> credentials;
@@ -108,5 +124,52 @@
       GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT));
 }
 
+TEST_F(BulkLeakCheckTest, CheckCredentialsAccessDoesNetworkRequest) {
+  AccountInfo info = identity_test_env().MakeAccountAvailable(kTestEmail);
+  identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
+  identity_test_env().SetRefreshTokenForAccount(info.account_id);
+
+  std::vector<LeakCheckCredential> credentials;
+  credentials.push_back(TestCredential("USERNAME@gmail.com"));
+  bulk_check().CheckCredentials(std::move(credentials));
+
+  auto network_request = std::make_unique<MockLeakDetectionRequest>();
+  EXPECT_CALL(*network_request,
+              LookupSingleLeak(
+                  _, kAccessToken,
+                  AllOf(Field(&LookupSingleLeakPayload::username_hash_prefix,
+                              ElementsAre(-67, 116, -87)),
+                        Field(&LookupSingleLeakPayload::encrypted_payload,
+                              testing::Ne(""))),
+                  _));
+  EXPECT_CALL(*request_factory(), CreateNetworkRequest)
+      .WillOnce(Return(ByMove(std::move(network_request))));
+  identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      kAccessToken, base::Time::Max());
+}
+
+TEST_F(BulkLeakCheckTest, CheckCredentialsMultipleNetworkRequests) {
+  AccountInfo info = identity_test_env().MakeAccountAvailable(kTestEmail);
+  identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
+  identity_test_env().SetRefreshTokenForAccount(info.account_id);
+
+  std::vector<LeakCheckCredential> credentials;
+  credentials.push_back(TestCredential("user1"));
+  credentials.push_back(TestCredential("user2"));
+  bulk_check().CheckCredentials(std::move(credentials));
+
+  auto network_request1 = std::make_unique<MockLeakDetectionRequest>();
+  auto network_request2 = std::make_unique<MockLeakDetectionRequest>();
+  EXPECT_CALL(*network_request1, LookupSingleLeak(_, kAccessToken, _, _));
+  EXPECT_CALL(*network_request2, LookupSingleLeak(_, kAccessToken, _, _));
+  EXPECT_CALL(*request_factory(), CreateNetworkRequest)
+      .WillOnce(Return(ByMove(std::move(network_request1))))
+      .WillOnce(Return(ByMove(std::move(network_request2))));
+  identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      kAccessToken, base::Time::Max());
+  identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      kAccessToken, base::Time::Max());
+}
+
 }  // namespace
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.cc b/components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.cc
new file mode 100644
index 0000000..bfe72c3
--- /dev/null
+++ b/components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.cc
@@ -0,0 +1,15 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h"
+
+namespace password_manager {
+
+MockLeakDetectionRequest::MockLeakDetectionRequest() = default;
+MockLeakDetectionRequest::~MockLeakDetectionRequest() = default;
+
+MockLeakDetectionRequestFactory::MockLeakDetectionRequestFactory() = default;
+MockLeakDetectionRequestFactory::~MockLeakDetectionRequestFactory() = default;
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h b/components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h
new file mode 100644
index 0000000..7d06205
--- /dev/null
+++ b/components/password_manager/core/browser/leak_detection/mock_leak_detection_request_factory.h
@@ -0,0 +1,43 @@
+// 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_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_REQUEST_FACTORY_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_REQUEST_FACTORY_H_
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace password_manager {
+
+class MockLeakDetectionRequest : public LeakDetectionRequestInterface {
+ public:
+  MockLeakDetectionRequest();
+  ~MockLeakDetectionRequest() override;
+
+  // LeakDetectionRequestInterface:
+  MOCK_METHOD(void,
+              LookupSingleLeak,
+              (network::mojom::URLLoaderFactory*,
+               const std::string&,
+               LookupSingleLeakPayload,
+               LookupSingleLeakCallback),
+              (override));
+};
+
+class MockLeakDetectionRequestFactory : public LeakDetectionRequestFactory {
+ public:
+  MockLeakDetectionRequestFactory();
+  ~MockLeakDetectionRequestFactory() override;
+
+  // LeakDetectionRequestFactory:
+  MOCK_METHOD(std::unique_ptr<LeakDetectionRequestInterface>,
+              CreateNetworkRequest,
+              (),
+              (const override));
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_REQUEST_FACTORY_H_
diff --git a/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.cc b/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.cc
index 699380e..831ada7 100644
--- a/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.cc
+++ b/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.cc
@@ -3,9 +3,50 @@
 // found in the LICENSE file.
 
 #include "components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h"
+
+#include <memory>
+#include <tuple>
+
 #include "base/logging.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 
 namespace password_manager {
+
+namespace {
+
+using autofill::PasswordForm;
+
+// Simple struct that stores a canonicalized credential.
+struct CanonicalizedCredential {
+  explicit CanonicalizedCredential(const PasswordForm& form)
+      : canonicalized_username(CanonicalizeUsername(form.username_value)),
+        password(form.password_value) {}
+
+  base::string16 canonicalized_username;
+  base::string16 password;
+};
+
+bool operator<(const CanonicalizedCredential& lhs,
+               const CanonicalizedCredential& rhs) {
+  return std::tie(lhs.canonicalized_username, lhs.password) <
+         std::tie(rhs.canonicalized_username, rhs.password);
+}
+
+}  // namespace
+
+const char kBulkLeakCheckDataKey[] = "bulk-leak-check-data";
+
+BulkLeakCheckData::BulkLeakCheckData(const PasswordForm& leaked_form)
+    : leaked_forms({leaked_form}) {}
+
+BulkLeakCheckData::BulkLeakCheckData(std::vector<PasswordForm> leaked_forms)
+    : leaked_forms(std::move(leaked_forms)) {}
+
+BulkLeakCheckData::~BulkLeakCheckData() = default;
+
 BulkLeakCheckServiceAdapter::BulkLeakCheckServiceAdapter(
     SavedPasswordsPresenter* presenter,
     BulkLeakCheckService* service)
@@ -19,14 +60,40 @@
   presenter_->RemoveObserver(this);
 }
 
-void BulkLeakCheckServiceAdapter::StartBulkLeakCheck() {
-  // TODO(crbug.com/1047726): Implement.
-  NOTIMPLEMENTED();
+bool BulkLeakCheckServiceAdapter::StartBulkLeakCheck() {
+  if (service_->state() == BulkLeakCheckService::State::kRunning)
+    return false;
+
+  // Even though the BulkLeakCheckService performs canonicalization eventually
+  // we do it here to de-dupe credentials that have the same canonicalized form.
+  // Each canonicalized credential is mapped to a list of saved passwords that
+  // correspond to this credential.
+  std::map<CanonicalizedCredential, std::vector<PasswordForm>> canonicalized;
+  for (const PasswordForm& form : presenter_->GetSavedPasswords())
+    canonicalized[CanonicalizedCredential(form)].push_back(form);
+
+  // Build the list of LeakCheckCredentials and attach the corresponding saved
+  // passwords as UserData. Lastly,forward them to the service to start the
+  // check.
+  std::vector<LeakCheckCredential> credentials;
+  credentials.reserve(canonicalized.size());
+
+  for (auto& pair : canonicalized) {
+    const CanonicalizedCredential& credential = pair.first;
+    std::vector<PasswordForm>& forms = pair.second;
+    credentials.emplace_back(credential.canonicalized_username,
+                             credential.password);
+    credentials.back().SetUserData(
+        kBulkLeakCheckDataKey,
+        std::make_unique<BulkLeakCheckData>(std::move(forms)));
+  }
+
+  service_->CheckUsernamePasswordPairs(std::move(credentials));
+  return true;
 }
 
 void BulkLeakCheckServiceAdapter::StopBulkLeakCheck() {
-  // TODO(crbug.com/1047726): Implement.
-  NOTIMPLEMENTED();
+  service_->Cancel();
 }
 
 BulkLeakCheckService::State BulkLeakCheckServiceAdapter::GetBulkLeakCheckState()
@@ -38,9 +105,14 @@
   return service_->GetPendingChecksCount();
 }
 
-void BulkLeakCheckServiceAdapter::OnEdited(const autofill::PasswordForm& form) {
-  // TODO(crbug.com/1047726): Implement.
-  NOTIMPLEMENTED();
+void BulkLeakCheckServiceAdapter::OnEdited(const PasswordForm& form) {
+  // Here no extra canonicalization is needed, as there are no other forms we
+  // could de-dupe before we pass it on to the service.
+  std::vector<LeakCheckCredential> credentials;
+  credentials.emplace_back(form.username_value, form.password_value);
+  credentials.back().SetUserData(kBulkLeakCheckDataKey,
+                                 std::make_unique<BulkLeakCheckData>(form));
+  service_->CheckUsernamePasswordPairs(std::move(credentials));
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h b/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h
index ba5905c..539f020 100644
--- a/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h
+++ b/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h
@@ -6,10 +6,30 @@
 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_BULK_LEAK_CHECK_SERVICE_ADAPTER_H_
 
 #include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 
+namespace autofill {
+struct PasswordForm;
+}
+
 namespace password_manager {
 
+// Key used to store an instance of BulkLeakCheckData in the user data map of a
+// LeakCheckCredential.
+extern const char kBulkLeakCheckDataKey[];
+
+// This struct bundles forms that correspond to the same LeakCheckCredential.
+// That is, all of the forms in |leaked_forms| correspond to the same pair of
+// canonicalized username and password.
+struct BulkLeakCheckData : LeakCheckCredential::Data {
+  explicit BulkLeakCheckData(const autofill::PasswordForm& leaked_form);
+  explicit BulkLeakCheckData(std::vector<autofill::PasswordForm> leaked_forms);
+  ~BulkLeakCheckData() override;
+
+  std::vector<autofill::PasswordForm> leaked_forms;
+};
+
 // This class serves as an apdater for the BulkLeakCheckService and exposes an
 // API that is intended to be consumed from the settings page.
 class BulkLeakCheckServiceAdapter : public SavedPasswordsPresenter::Observer {
@@ -18,10 +38,12 @@
                               BulkLeakCheckService* service);
   ~BulkLeakCheckServiceAdapter() override;
 
-  // Instructs the adapter to start a check. This will obtain the list of saved
-  // passwords from |presenter_|, perform de-duplication of username and
-  // password pairs and then feed it to the |service_| for checking.
-  void StartBulkLeakCheck();
+  // Instructs the adapter to start a check. This is a no-op in case a check is
+  // already running. Otherwise, this will obtain the list of saved passwords
+  // from |presenter_|, perform de-duplication of username and password pairs
+  // and then feed it to the |service_| for checking.
+  // Returns whether new check was started.
+  bool StartBulkLeakCheck();
 
   // This asks |service_| to stop an ongoing check.
   void StopBulkLeakCheck();
diff --git a/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc b/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc
index b63b5142..b414d90 100644
--- a/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc
+++ b/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc
@@ -4,10 +4,19 @@
 
 #include "components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h"
 
+#include <tuple>
+#include <vector>
+
+#include "base/containers/span.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_piece_forward.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/gmock_move_support.h"
 #include "base/test/task_environment.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
 #include "components/password_manager/core/browser/leak_detection/mock_leak_detection_check_factory.h"
 #include "components/password_manager/core/browser/test_password_store.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
@@ -20,13 +29,72 @@
 namespace password_manager {
 namespace {
 
+constexpr char kExampleCom[] = "https://example.com";
+constexpr char kExampleOrg[] = "https://example.org";
+
+constexpr char kUsername1[] = "alice";
+constexpr char kUsername2[] = "bob";
+
+constexpr char kPassword1[] = "f00b4r";
+constexpr char kPassword2[] = "s3cr3t";
+
+using autofill::PasswordForm;
+using ::testing::ByMove;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+MATCHER_P(CredentialsAre, credentials, "") {
+  return std::equal(arg.begin(), arg.end(), credentials.get().begin(),
+                    credentials.get().end(),
+                    [](const auto& lhs, const auto& rhs) {
+                      return lhs.username() == rhs.username() &&
+                             lhs.password() == rhs.password();
+                    });
+}
+
+MATCHER_P(SavedPasswordsAre, passwords, "") {
+  return std::equal(arg.begin(), arg.end(), passwords.begin(), passwords.end(),
+                    [](const auto& lhs, const auto& rhs) {
+                      return lhs.signon_realm == rhs.signon_realm &&
+                             lhs.username_value == rhs.username_value &&
+                             lhs.password_value == rhs.password_value;
+                    });
+}
+
+PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
+                               base::StringPiece username,
+                               base::StringPiece password) {
+  PasswordForm form;
+  form.signon_realm = std::string(signon_realm);
+  form.username_value = base::ASCIIToUTF16(username);
+  form.password_value = base::ASCIIToUTF16(password);
+  return form;
+}
+
+LeakCheckCredential MakeLeakCheckCredential(base::StringPiece username,
+                                            base::StringPiece password) {
+  return LeakCheckCredential(base::ASCIIToUTF16(username),
+                             base::ASCIIToUTF16(password));
+}
+
+struct MockBulkLeakCheck : BulkLeakCheck {
+  MOCK_METHOD(void,
+              CheckCredentials,
+              (std::vector<LeakCheckCredential> credentials),
+              (override));
+  MOCK_METHOD(size_t, GetPendingChecksCount, (), (const override));
+};
+
+using NiceMockBulkLeakCheck = ::testing::NiceMock<MockBulkLeakCheck>;
+
 class BulkLeakCheckServiceAdapterTest : public ::testing::Test {
  public:
   BulkLeakCheckServiceAdapterTest() {
-    service_.set_leak_factory(
-        std::make_unique<MockLeakDetectionCheckFactory>());
-
-    store_->Init(syncer::SyncableService::StartSyncFlare(), /*prefs=*/nullptr);
+    auto factory = std::make_unique<MockLeakDetectionCheckFactory>();
+    factory_ = factory.get();
+    service_.set_leak_factory(std::move(factory));
+    store_->Init(syncer::SyncableService::StartSyncFlare(),
+                 /*prefs=*/nullptr);
   }
 
   ~BulkLeakCheckServiceAdapterTest() override {
@@ -34,8 +102,13 @@
     task_env_.RunUntilIdle();
   }
 
+  TestPasswordStore& store() { return *store_; }
+  SavedPasswordsPresenter& presenter() { return presenter_; }
+  MockLeakDetectionCheckFactory& factory() { return *factory_; }
   BulkLeakCheckServiceAdapter& adapter() { return adapter_; }
 
+  void RunUntilIdle() { task_env_.RunUntilIdle(); }
+
  private:
   base::test::TaskEnvironment task_env_;
   signin::IdentityTestEnvironment identity_test_env_;
@@ -45,6 +118,7 @@
   BulkLeakCheckService service_{
       identity_test_env_.identity_manager(),
       base::MakeRefCounted<network::TestSharedURLLoaderFactory>()};
+  MockLeakDetectionCheckFactory* factory_ = nullptr;
   BulkLeakCheckServiceAdapter adapter_{&presenter_, &service_};
 };
 
@@ -56,4 +130,118 @@
             adapter().GetBulkLeakCheckState());
 }
 
+// Checks that starting a leak check correctly transforms the list of saved
+// passwords into LeakCheckCredentials and attaches the underlying password
+// forms as user data.
+TEST_F(BulkLeakCheckServiceAdapterTest, StartBulkLeakCheck) {
+  std::vector<PasswordForm> passwords = {
+      MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
+      MakeSavedPassword(kExampleOrg, kUsername2, kPassword2)};
+  store().AddLogin(passwords[0]);
+  store().AddLogin(passwords[1]);
+  RunUntilIdle();
+
+  auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
+  std::vector<LeakCheckCredential> credentials;
+  EXPECT_CALL(*leak_check, CheckCredentials).WillOnce(MoveArg(&credentials));
+  EXPECT_CALL(factory(), TryCreateBulkLeakCheck)
+      .WillOnce(Return(ByMove(std::move(leak_check))));
+  adapter().StartBulkLeakCheck();
+
+  std::vector<LeakCheckCredential> expected;
+  expected.push_back(MakeLeakCheckCredential(kUsername1, kPassword1));
+  expected.push_back(MakeLeakCheckCredential(kUsername2, kPassword2));
+
+  EXPECT_THAT(credentials, CredentialsAre(std::cref(expected)));
+
+  EXPECT_THAT(static_cast<BulkLeakCheckData*>(
+                  credentials[0].GetUserData(kBulkLeakCheckDataKey))
+                  ->leaked_forms,
+              SavedPasswordsAre(base::make_span(&passwords[0], 1)));
+
+  EXPECT_THAT(static_cast<BulkLeakCheckData*>(
+                  credentials[1].GetUserData(kBulkLeakCheckDataKey))
+                  ->leaked_forms,
+              SavedPasswordsAre(base::make_span(&passwords[1], 1)));
+}
+
+// Tests that multiple credentials with effectively the same username are
+// correctly deduped before starting the leak check.
+TEST_F(BulkLeakCheckServiceAdapterTest, StartBulkLeakCheckDedupes) {
+  std::vector<PasswordForm> passwords = {
+      MakeSavedPassword(kExampleCom, "alice", kPassword1),
+      MakeSavedPassword(kExampleCom, "ALICE", kPassword1),
+      MakeSavedPassword(kExampleCom, "Alice@example.com", kPassword1)};
+
+  store().AddLogin(passwords[0]);
+  store().AddLogin(passwords[1]);
+  store().AddLogin(passwords[2]);
+  RunUntilIdle();
+
+  auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
+  std::vector<LeakCheckCredential> credentials;
+  EXPECT_CALL(*leak_check, CheckCredentials).WillOnce(MoveArg(&credentials));
+  EXPECT_CALL(factory(), TryCreateBulkLeakCheck)
+      .WillOnce(Return(ByMove(std::move(leak_check))));
+  adapter().StartBulkLeakCheck();
+
+  std::vector<LeakCheckCredential> expected;
+  expected.push_back(MakeLeakCheckCredential("alice", kPassword1));
+  EXPECT_THAT(credentials, CredentialsAre(std::cref(expected)));
+
+  EXPECT_THAT(static_cast<BulkLeakCheckData*>(
+                  credentials[0].GetUserData(kBulkLeakCheckDataKey))
+                  ->leaked_forms,
+              SavedPasswordsAre(passwords));
+}
+
+// Checks that trying to start a leak check when another check is already
+// running does nothing and returns false to the caller.
+TEST_F(BulkLeakCheckServiceAdapterTest, MultipleStarts) {
+  auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
+  auto& leak_check_ref = *leak_check;
+  EXPECT_CALL(leak_check_ref, CheckCredentials);
+  EXPECT_CALL(factory(), TryCreateBulkLeakCheck)
+      .WillOnce(Return(ByMove(std::move(leak_check))));
+  EXPECT_TRUE(adapter().StartBulkLeakCheck());
+
+  EXPECT_CALL(leak_check_ref, CheckCredentials).Times(0);
+  EXPECT_FALSE(adapter().StartBulkLeakCheck());
+}
+
+// Checks that stopping the leak check correctly resets the state of the bulk
+// leak check.
+TEST_F(BulkLeakCheckServiceAdapterTest, StopBulkLeakCheck) {
+  auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
+  EXPECT_CALL(*leak_check, CheckCredentials);
+  EXPECT_CALL(factory(), TryCreateBulkLeakCheck)
+      .WillOnce(Return(ByMove(std::move(leak_check))));
+  adapter().StartBulkLeakCheck();
+  EXPECT_EQ(BulkLeakCheckService::State::kRunning,
+            adapter().GetBulkLeakCheckState());
+
+  adapter().StopBulkLeakCheck();
+  EXPECT_EQ(BulkLeakCheckService::State::kIdle,
+            adapter().GetBulkLeakCheckState());
+}
+
+// Tests that editing a password through the presenter will result in another
+// call to CheckCredentials with a corresponding change to the checked password.
+TEST_F(BulkLeakCheckServiceAdapterTest, OnEdited) {
+  PasswordForm password =
+      MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
+  store().AddLogin(password);
+  RunUntilIdle();
+
+  std::vector<LeakCheckCredential> expected;
+  expected.push_back(MakeLeakCheckCredential(kUsername1, kPassword2));
+
+  auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
+  EXPECT_CALL(*leak_check,
+              CheckCredentials(CredentialsAre(std::cref(expected))));
+  EXPECT_CALL(factory(), TryCreateBulkLeakCheck)
+      .WillOnce(Return(ByMove(std::move(leak_check))));
+  presenter().EditPassword(password, base::ASCIIToUTF16(kPassword2));
+}
+
 }  // namespace password_manager
diff --git a/components/performance_manager/worker_watcher.cc b/components/performance_manager/worker_watcher.cc
index ce64c29..bbcc2d0 100644
--- a/components/performance_manager/worker_watcher.cc
+++ b/components/performance_manager/worker_watcher.cc
@@ -42,6 +42,18 @@
     worker_node->RemoveClientFrame(frame_node);
 }
 
+// Helper function that posts a task on the PM sequence that will invoke
+// OnFinalResponseURLDetermined() on |worker_node|.
+void SetFinalResponseURL(WorkerNodeImpl* worker_node, const GURL& url) {
+  PerformanceManagerImpl::CallOnGraphImpl(
+      FROM_HERE,
+      base::BindOnce(
+          [](WorkerNodeImpl* worker_node, const GURL& url, GraphImpl* graph) {
+            worker_node->OnFinalResponseURLDetermined(url);
+          },
+          worker_node, url));
+}
+
 }  // namespace
 
 WorkerWatcher::WorkerWatcher(
@@ -140,6 +152,12 @@
   dedicated_worker_nodes_.erase(it);
 }
 
+void WorkerWatcher::OnFinalResponseURLDetermined(
+    content::DedicatedWorkerId dedicated_worker_id,
+    const GURL& url) {
+  SetFinalResponseURL(GetDedicatedWorkerNode(dedicated_worker_id), url);
+}
+
 void WorkerWatcher::OnWorkerStarted(
     content::SharedWorkerId shared_worker_id,
     int worker_process_id,
@@ -167,6 +185,12 @@
   shared_worker_nodes_.erase(it);
 }
 
+void WorkerWatcher::OnFinalResponseURLDetermined(
+    content::SharedWorkerId shared_worker_id,
+    const GURL& url) {
+  SetFinalResponseURL(GetSharedWorkerNode(shared_worker_id), url);
+}
+
 void WorkerWatcher::OnClientAdded(
     content::SharedWorkerId shared_worker_id,
     content::GlobalFrameRoutingId render_frame_host_id) {
diff --git a/components/performance_manager/worker_watcher.h b/components/performance_manager/worker_watcher.h
index f19e1f5..8bec185 100644
--- a/components/performance_manager/worker_watcher.h
+++ b/components/performance_manager/worker_watcher.h
@@ -50,6 +50,9 @@
   void OnBeforeWorkerTerminated(
       content::DedicatedWorkerId dedicated_worker_id,
       content::GlobalFrameRoutingId ancestor_render_frame_host_id) override;
+  void OnFinalResponseURLDetermined(
+      content::DedicatedWorkerId dedicated_worker_id,
+      const GURL& url) override;
 
   // content::SharedWorkerService::Observer:
   void OnWorkerStarted(content::SharedWorkerId shared_worker_id,
@@ -57,6 +60,8 @@
                        const base::UnguessableToken& dev_tools_token) override;
   void OnBeforeWorkerTerminated(
       content::SharedWorkerId shared_worker_id) override;
+  void OnFinalResponseURLDetermined(content::SharedWorkerId shared_worker_id,
+                                    const GURL& url) override;
   void OnClientAdded(
       content::SharedWorkerId shared_worker_id,
       content::GlobalFrameRoutingId render_frame_host_id) override;
diff --git a/components/safe_browsing/android/remote_database_manager.cc b/components/safe_browsing/android/remote_database_manager.cc
index b0298ecd..1a6d62f3 100644
--- a/components/safe_browsing/android/remote_database_manager.cc
+++ b/components/safe_browsing/android/remote_database_manager.cc
@@ -342,8 +342,6 @@
   VLOG(1) << "RemoteSafeBrowsingDatabaseManager starting";
   SafeBrowsingDatabaseManager::StartOnIOThread(url_loader_factory, config);
 
-  SetupRealTimeUrlLookupService(url_loader_factory);
-
   enabled_ = true;
 }
 
@@ -361,8 +359,6 @@
   }
   enabled_ = false;
 
-  ResetRealTimeUrlLookupService();
-
   SafeBrowsingDatabaseManager::StopOnIOThread(shutdown);
 }
 
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
index 0594d07..59b837972 100644
--- a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
+++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
@@ -12,6 +12,7 @@
 #include "components/safe_browsing/core/common/safebrowsing_constants.h"
 #include "components/safe_browsing/core/common/utils.h"
 #include "components/safe_browsing/core/realtime/policy_engine.h"
+#include "components/safe_browsing/core/realtime/url_lookup_service.h"
 #include "components/safe_browsing/core/verdict_cache_manager.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -35,14 +36,16 @@
       base::WeakPtr<BrowserURLLoaderThrottle> throttle,
       bool real_time_lookup_enabled,
       base::WeakPtr<VerdictCacheManager> cache_manager,
-      signin::IdentityManager* identity_manager)
+      signin::IdentityManager* identity_manager,
+      base::WeakPtr<RealTimeUrlLookupService> url_lookup_service)
       : delegate_getter_(std::move(delegate_getter)),
         frame_tree_node_id_(frame_tree_node_id),
         web_contents_getter_(web_contents_getter),
         throttle_(std::move(throttle)),
         real_time_lookup_enabled_(real_time_lookup_enabled),
         cache_manager_(cache_manager),
-        identity_manager_(identity_manager) {}
+        identity_manager_(identity_manager),
+        url_lookup_service_(url_lookup_service) {}
 
   // Starts the initial safe browsing check. This check and future checks may be
   // skipped after checking with the UrlCheckerDelegate.
@@ -72,7 +75,7 @@
     url_checker_ = std::make_unique<SafeBrowsingUrlCheckerImpl>(
         headers, load_flags, resource_type, has_user_gesture,
         url_checker_delegate, web_contents_getter_, real_time_lookup_enabled_,
-        cache_manager_, identity_manager_);
+        cache_manager_, identity_manager_, url_lookup_service_);
 
     CheckUrl(url, method);
   }
@@ -141,6 +144,7 @@
   bool real_time_lookup_enabled_ = false;
   base::WeakPtr<VerdictCacheManager> cache_manager_;
   signin::IdentityManager* identity_manager_;
+  base::WeakPtr<RealTimeUrlLookupService> url_lookup_service_;
 };
 
 // static
@@ -149,11 +153,12 @@
     const base::RepeatingCallback<content::WebContents*()>& web_contents_getter,
     int frame_tree_node_id,
     base::WeakPtr<VerdictCacheManager> cache_manager,
-    signin::IdentityManager* identity_manager) {
+    signin::IdentityManager* identity_manager,
+    base::WeakPtr<RealTimeUrlLookupService> url_lookup_service) {
   return base::WrapUnique<BrowserURLLoaderThrottle>(
-      new BrowserURLLoaderThrottle(std::move(delegate_getter),
-                                   web_contents_getter, frame_tree_node_id,
-                                   cache_manager, identity_manager));
+      new BrowserURLLoaderThrottle(
+          std::move(delegate_getter), web_contents_getter, frame_tree_node_id,
+          cache_manager, identity_manager, url_lookup_service));
 }
 
 BrowserURLLoaderThrottle::BrowserURLLoaderThrottle(
@@ -161,7 +166,8 @@
     const base::RepeatingCallback<content::WebContents*()>& web_contents_getter,
     int frame_tree_node_id,
     base::WeakPtr<VerdictCacheManager> cache_manager,
-    signin::IdentityManager* identity_manager) {
+    signin::IdentityManager* identity_manager,
+    base::WeakPtr<RealTimeUrlLookupService> url_lookup_service) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Decide whether to do real time URL lookups or not.
@@ -174,7 +180,7 @@
   io_checker_ = std::make_unique<CheckerOnIO>(
       std::move(delegate_getter), frame_tree_node_id, web_contents_getter,
       weak_factory_.GetWeakPtr(), real_time_lookup_enabled, cache_manager,
-      identity_manager);
+      identity_manager, url_lookup_service);
 }
 
 BrowserURLLoaderThrottle::~BrowserURLLoaderThrottle() {
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.h b/components/safe_browsing/content/browser/browser_url_loader_throttle.h
index b5e7d2fc..515e161 100644
--- a/components/safe_browsing/content/browser/browser_url_loader_throttle.h
+++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.h
@@ -34,6 +34,8 @@
 
 class VerdictCacheManager;
 
+class RealTimeUrlLookupService;
+
 // BrowserURLLoaderThrottle is used in the browser process to query
 // SafeBrowsing to determine whether a URL and also its redirect URLs are safe
 // to load.
@@ -54,7 +56,8 @@
           web_contents_getter,
       int frame_tree_node_id,
       base::WeakPtr<VerdictCacheManager> cache_manager,
-      signin::IdentityManager* identity_manager);
+      signin::IdentityManager* identity_manager,
+      base::WeakPtr<RealTimeUrlLookupService> url_lookup_service);
 
   ~BrowserURLLoaderThrottle() override;
 
@@ -90,7 +93,8 @@
           web_contents_getter,
       int frame_tree_node_id,
       base::WeakPtr<VerdictCacheManager> cache_manager,
-      signin::IdentityManager* identity_manager);
+      signin::IdentityManager* identity_manager,
+      base::WeakPtr<RealTimeUrlLookupService> url_lookup_service);
 
   // |slow_check| indicates whether it reports the result of a slow check.
   // (Please see comments of CheckerOnIO::OnCheckUrlResult() for what slow check
diff --git a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
index 7a409b6..dd9f286 100644
--- a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
+++ b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
@@ -148,16 +148,17 @@
   }
 
   // This is not called for frame resources, and real time URL checks currently
-  // only support frame resources. If we extend real time URL checks to support
-  // non-main frames, we will need to provide the user preferences, cache
-  // manager and identity_manager regarding real time lookup here.
+  // only support main frame resources. If we extend real time URL checks to
+  // support non-main frames, we will need to provide the user preferences,
+  // cache manager, identity_manager and url_lookup_service regarding real time
+  // lookup here.
   auto checker_impl = std::make_unique<SafeBrowsingUrlCheckerImpl>(
       headers, static_cast<int>(load_flags), resource_type, has_user_gesture,
       delegate_,
       base::BindRepeating(&GetWebContentsFromID, render_process_id_,
                           static_cast<int>(render_frame_id)),
       /*real_time_lookup_enabled=*/false, /*cache_manager=*/nullptr,
-      /*identity_manager=*/nullptr);
+      /*identity_manager=*/nullptr, /* url_lookup_service */ nullptr);
 
   checker_impl->CheckUrl(
       url, method,
diff --git a/components/safe_browsing/content/browser/safe_browsing_url_checker_impl_content.cc b/components/safe_browsing/content/browser/safe_browsing_url_checker_impl_content.cc
index 2c76619..505569d3 100644
--- a/components/safe_browsing/content/browser/safe_browsing_url_checker_impl_content.cc
+++ b/components/safe_browsing/content/browser/safe_browsing_url_checker_impl_content.cc
@@ -20,20 +20,9 @@
 namespace safe_browsing {
 
 bool SafeBrowsingUrlCheckerImpl::CanPerformFullURLLookup(const GURL& url) {
-  if (!real_time_lookup_enabled_)
-    return false;
-
-  if (!RealTimePolicyEngine::CanPerformFullURLLookupForResourceType(
-          resource_type_))
-    return false;
-
-  auto* rt_lookup_service = database_manager_->GetRealTimeUrlLookupService();
-  if (!rt_lookup_service || !rt_lookup_service->CanCheckUrl(url))
-    return false;
-
-  bool in_backoff = rt_lookup_service->IsInBackoffMode();
-  UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.RT.Backoff.State", in_backoff);
-  return !in_backoff;
+  return real_time_lookup_enabled_ &&
+         RealTimePolicyEngine::CanPerformFullURLLookupForResourceType(
+             resource_type_);
 }
 
 void SafeBrowsingUrlCheckerImpl::OnRTLookupRequest(
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
index ff1009f..0f8cd85 100644
--- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
+++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
@@ -104,7 +104,8 @@
     const base::RepeatingCallback<content::WebContents*()>& web_contents_getter,
     bool real_time_lookup_enabled,
     base::WeakPtr<VerdictCacheManager> cache_manager_on_ui,
-    signin::IdentityManager* identity_manager_on_ui)
+    signin::IdentityManager* identity_manager_on_ui,
+    base::WeakPtr<RealTimeUrlLookupService> url_lookup_service_on_ui)
     : headers_(headers),
       load_flags_(load_flags),
       resource_type_(static_cast<ResourceType>(resource_type)),
@@ -114,7 +115,8 @@
       database_manager_(url_checker_delegate_->GetDatabaseManager()),
       real_time_lookup_enabled_(real_time_lookup_enabled),
       cache_manager_on_ui_(cache_manager_on_ui),
-      identity_manager_on_ui_(identity_manager_on_ui) {}
+      identity_manager_on_ui_(identity_manager_on_ui),
+      url_lookup_service_on_ui_(url_lookup_service_on_ui) {}
 
 SafeBrowsingUrlCheckerImpl::~SafeBrowsingUrlCheckerImpl() {
   DCHECK(CurrentlyOnThread(ThreadID::IO));
@@ -492,24 +494,46 @@
     return;
   }
 
-  RTLookupRequestCallback request_callback =
-      base::BindOnce(&SafeBrowsingUrlCheckerImpl::OnRTLookupRequest,
-                     weak_factory_.GetWeakPtr());
-
-  RTLookupResponseCallback response_callback =
-      base::BindOnce(&SafeBrowsingUrlCheckerImpl::OnRTLookupResponse,
-                     weak_factory_.GetWeakPtr());
-
-  auto* rt_lookup_service = database_manager_->GetRealTimeUrlLookupService();
-  rt_lookup_service->StartLookup(url, std::move(request_callback),
-                                 std::move(response_callback),
-                                 identity_manager_on_ui_);
+  base::PostTask(
+      FROM_HERE, CreateTaskTraits(ThreadID::UI),
+      base::BindOnce(&SafeBrowsingUrlCheckerImpl::StartLookupOnUIThread,
+                     weak_factory_.GetWeakPtr(), url, url_lookup_service_on_ui_,
+                     database_manager_, identity_manager_on_ui_));
 }
 
 void SafeBrowsingUrlCheckerImpl::SetWebUIToken(int token) {
   url_web_ui_token_ = token;
 }
 
+// static
+void SafeBrowsingUrlCheckerImpl::StartLookupOnUIThread(
+    base::WeakPtr<SafeBrowsingUrlCheckerImpl> weak_checker_on_io,
+    const GURL& url,
+    base::WeakPtr<RealTimeUrlLookupService> url_lookup_service_on_ui,
+    scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
+    signin::IdentityManager* identity_manager) {
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
+  if (!url_lookup_service_on_ui ||
+      !url_lookup_service_on_ui->CanCheckUrl(url) ||
+      url_lookup_service_on_ui->IsInBackoffMode()) {
+    base::PostTask(
+        FROM_HERE, CreateTaskTraits(ThreadID::IO),
+        base::BindOnce(&SafeBrowsingUrlCheckerImpl::PerformHashBasedCheck,
+                       weak_checker_on_io, url));
+    return;
+  }
+
+  RTLookupRequestCallback request_callback = base::BindOnce(
+      &SafeBrowsingUrlCheckerImpl::OnRTLookupRequest, weak_checker_on_io);
+
+  RTLookupResponseCallback response_callback = base::BindOnce(
+      &SafeBrowsingUrlCheckerImpl::OnRTLookupResponse, weak_checker_on_io);
+
+  url_lookup_service_on_ui->StartLookup(url, std::move(request_callback),
+                                        std::move(response_callback),
+                                        identity_manager);
+}
+
 void SafeBrowsingUrlCheckerImpl::PerformHashBasedCheck(const GURL& url) {
   DCHECK(CurrentlyOnThread(ThreadID::IO));
   browse_url_check_sent_ = true;
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
index 14b71251..8fee6f7 100644
--- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
+++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
@@ -40,6 +40,8 @@
 
 class VerdictCacheManager;
 
+class RealTimeUrlLookupService;
+
 // A SafeBrowsingUrlCheckerImpl instance is used to perform SafeBrowsing check
 // for a URL and its redirect URLs. It implements Mojo interface so that it can
 // be used to handle queries from renderers. But it is also used to handle
@@ -75,6 +77,10 @@
   // indicates whether or not the profile has enabled real time URL lookups, as
   // computed by the RealTimePolicyEngine. This must be computed in advance,
   // since this class only exists on the IO thread.
+  // TODO(crbug.com/1050859): Move |real_time_lookup_enabled|,
+  // |cache_manager_on_ui| and |identity_manager_on_ui| into
+  // url_lookup_service_on_ui, and reduce the number of parameters in this
+  // constructor.
   SafeBrowsingUrlCheckerImpl(
       const net::HttpRequestHeaders& headers,
       int load_flags,
@@ -85,7 +91,8 @@
           web_contents_getter,
       bool real_time_lookup_enabled,
       base::WeakPtr<VerdictCacheManager> cache_manager_on_ui,
-      signin::IdentityManager* identity_manager_on_ui);
+      signin::IdentityManager* identity_manager_on_ui,
+      base::WeakPtr<RealTimeUrlLookupService> url_lookup_service_on_ui);
 
   ~SafeBrowsingUrlCheckerImpl() override;
 
@@ -179,6 +186,17 @@
   // Perform the hash based check for the url.
   void PerformHashBasedCheck(const GURL& url);
 
+  // This function has to be static because it is called in UI thread.
+  // This function starts a real time url check if |url_lookup_service_on_ui| is
+  // available and is not in backoff mode. Otherwise, hop back to IO thread and
+  // perform hash based check.
+  static void StartLookupOnUIThread(
+      base::WeakPtr<SafeBrowsingUrlCheckerImpl> weak_checker_on_io,
+      const GURL& url,
+      base::WeakPtr<RealTimeUrlLookupService> url_lookup_service_on_ui,
+      scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
+      signin::IdentityManager* identity_manager);
+
   // Called when the |request| from the real-time lookup service is sent.
   void OnRTLookupRequest(std::unique_ptr<RTLookupRequest> request);
 
@@ -252,6 +270,10 @@
   // token is enabled. Can only be accessed in UI thread.
   signin::IdentityManager* identity_manager_on_ui_;
 
+  // This object is used to perform real time url check. Can only be accessed in
+  // UI thread.
+  base::WeakPtr<RealTimeUrlLookupService> url_lookup_service_on_ui_;
+
   base::WeakPtrFactory<SafeBrowsingUrlCheckerImpl> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingUrlCheckerImpl);
diff --git a/components/safe_browsing/core/db/BUILD.gn b/components/safe_browsing/core/db/BUILD.gn
index 9f53030..967e6ef 100644
--- a/components/safe_browsing/core/db/BUILD.gn
+++ b/components/safe_browsing/core/db/BUILD.gn
@@ -49,7 +49,6 @@
     ":v4_protocol_manager_util",
     "//base",
     "//components/safe_browsing/core/common:thread_utils",
-    "//components/safe_browsing/core/realtime:url_lookup_service",
     "//net",
     "//services/network/public/cpp",
     "//url",
diff --git a/components/safe_browsing/core/db/database_manager.cc b/components/safe_browsing/core/db/database_manager.cc
index 02ba00ec7..f096a56 100644
--- a/components/safe_browsing/core/db/database_manager.cc
+++ b/components/safe_browsing/core/db/database_manager.cc
@@ -13,7 +13,6 @@
 #include "components/safe_browsing/core/common/thread_utils.h"
 #include "components/safe_browsing/core/db/v4_get_hash_protocol_manager.h"
 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
-#include "components/safe_browsing/core/realtime/url_lookup_service.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "url/gurl.h"
 
@@ -139,24 +138,6 @@
   v4_get_hash_protocol_manager_.reset();
 }
 
-RealTimeUrlLookupService*
-SafeBrowsingDatabaseManager::GetRealTimeUrlLookupService() {
-  return rt_url_lookup_service_.get();
-}
-
-void SafeBrowsingDatabaseManager::SetupRealTimeUrlLookupService(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
-
-  rt_url_lookup_service_ =
-      std::make_unique<RealTimeUrlLookupService>(url_loader_factory);
-}
-
-void SafeBrowsingDatabaseManager::ResetRealTimeUrlLookupService() {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
-  rt_url_lookup_service_.reset();
-}
-
 std::unique_ptr<base::CallbackList<void()>::Subscription>
 SafeBrowsingDatabaseManager::RegisterDatabaseUpdatedCallback(
     const OnDatabaseUpdated& cb) {
@@ -173,29 +154,9 @@
   return "";
 }
 
-void SafeBrowsingDatabaseManager::OnProfileWillBeDestroyedOnIOThread(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
-  // |rt_url_lookup_service_| can be null in tests.
-  if (!rt_url_lookup_service_)
-    return;
-  // Reset |rt_url_lookup_service| if any one of the profiles will be destroyed.
-  // This is to make sure that all profile related operations are safe in
-  // |rt_url_lookup_service|. The old lookup service will finish all pending
-  // requests and delete itself.
-  RealTimeUrlLookupService* rt_url_lookup_service_raw =
-      rt_url_lookup_service_.release();
-  // Will delete |rt_url_lookup_service_raw|
-  rt_url_lookup_service_raw->WaitForPendingRequestsOrDelete();
-  rt_url_lookup_service_.reset(
-      new RealTimeUrlLookupService(url_loader_factory));
-}
-
 SafeBrowsingDatabaseManager::SafeBrowsingApiCheck::SafeBrowsingApiCheck(
     const GURL& url,
     Client* client)
     : url_(url), client_(client) {}
 
-SafeBrowsingDatabaseManager::SafeBrowsingApiCheck::~SafeBrowsingApiCheck() {}
-
 }  // namespace safe_browsing
diff --git a/components/safe_browsing/core/db/database_manager.h b/components/safe_browsing/core/db/database_manager.h
index c075f61..59f0c87 100644
--- a/components/safe_browsing/core/db/database_manager.h
+++ b/components/safe_browsing/core/db/database_manager.h
@@ -35,8 +35,6 @@
 
 namespace safe_browsing {
 
-class RealTimeUrlLookupService;
-
 // Value returned by some functions that check an allowlist and may or may not
 // have an immediate answer.
 enum class AsyncMatch : int {
@@ -272,27 +270,12 @@
   // method at the bottom of it.
   virtual void StopOnIOThread(bool shutdown);
 
-  // TODO(crbug.com/1041912): Add tests for this method.
-  // Called to notify operations on the io_thread. This is called when any
-  // profile will be destroyed.
-  void OnProfileWillBeDestroyedOnIOThread(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
-
-  // Instantiates and initializes |rt_url_lookup_service_|.
-  void SetupRealTimeUrlLookupService(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
-
-  // Reset |rt_url_lookup_service_|.
-  void ResetRealTimeUrlLookupService();
-
-  RealTimeUrlLookupService* GetRealTimeUrlLookupService();
-
  protected:
   // Bundled client info for an API abuse hash prefix check.
   class SafeBrowsingApiCheck {
    public:
     SafeBrowsingApiCheck(const GURL& url, Client* client);
-    ~SafeBrowsingApiCheck();
+    ~SafeBrowsingApiCheck() = default;
 
     const GURL& url() const { return url_; }
     Client* client() const { return client_; }
@@ -363,10 +346,6 @@
   // Returns an iterator to the pending API check with the given |client|.
   ApiCheckSet::iterator FindClientApiCheck(Client* client);
 
-  // This object gets refreshed when any active profile is destroyed. The old
-  // object is release and will delete itself when there is no pending request
-  // left.
-  std::unique_ptr<RealTimeUrlLookupService> rt_url_lookup_service_;
 };  // class SafeBrowsingDatabaseManager
 
 }  // namespace safe_browsing
diff --git a/components/safe_browsing/core/db/hit_report.h b/components/safe_browsing/core/db/hit_report.h
index 3240932..8bc0796 100644
--- a/components/safe_browsing/core/db/hit_report.h
+++ b/components/safe_browsing/core/db/hit_report.h
@@ -45,6 +45,7 @@
   std::string population_id;
 
   ExtendedReportingLevel extended_reporting_level;
+  bool is_enhanced_protection = false;
   bool is_metrics_reporting_active;
 
   std::string post_data;
diff --git a/components/safe_browsing/core/db/v4_local_database_manager.cc b/components/safe_browsing/core/db/v4_local_database_manager.cc
index e7ff8547..d5600a33 100644
--- a/components/safe_browsing/core/db/v4_local_database_manager.cc
+++ b/components/safe_browsing/core/db/v4_local_database_manager.cc
@@ -518,7 +518,6 @@
   db_updated_callback_ = base::BindRepeating(
       &V4LocalDatabaseManager::DatabaseUpdated, weak_factory_.GetWeakPtr());
 
-  SetupRealTimeUrlLookupService(url_loader_factory);
   SetupUpdateProtocolManager(url_loader_factory, config);
   SetupDatabase();
 
@@ -543,8 +542,6 @@
   // and doesn't block the IO thread.
   V4Database::Destroy(std::move(v4_database_));
 
-  ResetRealTimeUrlLookupService();
-
   // Delete the V4UpdateProtocolManager.
   // This cancels any in-flight update request.
   v4_update_protocol_manager_.reset();
diff --git a/components/safe_browsing/core/db/v4_protocol_manager_util.cc b/components/safe_browsing/core/db/v4_protocol_manager_util.cc
index d220a044..2c17c0a 100644
--- a/components/safe_browsing/core/db/v4_protocol_manager_util.cc
+++ b/components/safe_browsing/core/db/v4_protocol_manager_util.cc
@@ -89,7 +89,8 @@
 
 std::string GetReportUrl(const V4ProtocolConfig& config,
                          const std::string& method,
-                         const ExtendedReportingLevel* reporting_level) {
+                         const ExtendedReportingLevel* reporting_level,
+                         const bool is_enhanced_protection) {
   std::string url = base::StringPrintf(
       "%s/%s?client=%s&appver=%s&pver=4.0", kSbReportsURLPrefix, method.c_str(),
       config.client_name.c_str(), config.version.c_str());
@@ -100,6 +101,8 @@
   }
   if (reporting_level)
     url.append(base::StringPrintf("&ext=%d", *reporting_level));
+  if (is_enhanced_protection)
+    url.append(base::StringPrintf("&enh=%d", is_enhanced_protection));
   return url;
 }
 
diff --git a/components/safe_browsing/core/db/v4_protocol_manager_util.h b/components/safe_browsing/core/db/v4_protocol_manager_util.h
index cc43f2fe..b81ab05 100644
--- a/components/safe_browsing/core/db/v4_protocol_manager_util.h
+++ b/components/safe_browsing/core/db/v4_protocol_manager_util.h
@@ -89,7 +89,8 @@
 std::string GetReportUrl(
     const V4ProtocolConfig& config,
     const std::string& method,
-    const ExtendedReportingLevel* reporting_level = nullptr);
+    const ExtendedReportingLevel* reporting_level = nullptr,
+    const bool is_enhanced_protection = false);
 
 // Different types of threats that SafeBrowsing protects against. This is the
 // type that's returned to the clients of SafeBrowsing in Chromium.
diff --git a/components/safe_browsing/core/features.cc b/components/safe_browsing/core/features.cc
index 4cb0821..1a60d90b 100644
--- a/components/safe_browsing/core/features.cc
+++ b/components/safe_browsing/core/features.cc
@@ -72,8 +72,13 @@
 const base::Feature kPromptAppForDeepScanning{
     "SafeBrowsingPromptAppForDeepScanning", base::FEATURE_DISABLED_BY_DEFAULT};
 
+#if BUILDFLAG(FULL_SAFE_BROWSING)
+const base::Feature kRealTimeUrlLookupEnabled{
+    "SafeBrowsingRealTimeUrlLookupEnabled", base::FEATURE_ENABLED_BY_DEFAULT};
+#else
 const base::Feature kRealTimeUrlLookupEnabled{
     "SafeBrowsingRealTimeUrlLookupEnabled", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
 
 const base::Feature kRealTimeUrlLookupEnabledWithToken{
     "SafeBrowsingRealTimeUrlLookupEnabledWithToken",
diff --git a/components/safe_browsing/core/ping_manager.cc b/components/safe_browsing/core/ping_manager.cc
index be1cfdfb..3f2cde6 100644
--- a/components/safe_browsing/core/ping_manager.cc
+++ b/components/safe_browsing/core/ping_manager.cc
@@ -140,7 +140,8 @@
          hit_report.threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING ||
          hit_report.threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE);
   std::string url =
-      GetReportUrl(config_, "report", &hit_report.extended_reporting_level);
+      GetReportUrl(config_, "report", &hit_report.extended_reporting_level,
+                   hit_report.is_enhanced_protection);
   std::string threat_list = "none";
   switch (hit_report.threat_type) {
     case SB_THREAT_TYPE_URL_MALWARE:
diff --git a/components/safe_browsing/core/ping_manager_unittest.cc b/components/safe_browsing/core/ping_manager_unittest.cc
index be1a504b..ed2d135 100644
--- a/components/safe_browsing/core/ping_manager_unittest.cc
+++ b/components/safe_browsing/core/ping_manager_unittest.cc
@@ -57,12 +57,13 @@
     hp.is_subresource = true;
     hp.extended_reporting_level = SBER_LEVEL_LEGACY;
     hp.is_metrics_reporting_active = true;
+    hp.is_enhanced_protection = true;
 
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
             key_param_ +
-            "&ext=1&evts=malblhit&evtd=http%3A%2F%2Fmalicious.url.com%2F&"
+            "&ext=1&enh=1&evts=malblhit&evtd=http%3A%2F%2Fmalicious.url.com%2F&"
             "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer."
             "url.com%2F&evtb=1&src=l3&m=1",
         ping_manager()->SafeBrowsingHitUrl(hp).spec());
@@ -75,6 +76,7 @@
     hp.is_subresource = false;
     hp.extended_reporting_level = SBER_LEVEL_LEGACY;
     hp.is_metrics_reporting_active = true;
+    hp.is_enhanced_protection = false;
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
@@ -93,11 +95,12 @@
     hp.is_subresource = false;
     hp.extended_reporting_level = SBER_LEVEL_SCOUT;
     hp.is_metrics_reporting_active = true;
+    hp.is_enhanced_protection = true;
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
             key_param_ +
-            "&ext=2&evts=phishblhit&"
+            "&ext=2&enh=1&evts=phishblhit&"
             "evtd=http%3A%2F%2Fmalicious.url.com%2F&"
             "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer."
             "url.com%2F&evtb=0&src=ds&m=1",
@@ -111,11 +114,12 @@
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = true;
     hp.is_subresource = false;
+    hp.is_enhanced_protection = true;
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
             key_param_ +
-            "&ext=0&evts=binurlhit&"
+            "&ext=0&enh=1&evts=binurlhit&"
             "evtd=http%3A%2F%2Fmalicious.url.com%2F&"
             "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer."
             "url.com%2F&evtb=0&src=rem&m=1",
@@ -129,11 +133,12 @@
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = false;
     hp.is_subresource = false;
+    hp.is_enhanced_protection = true;
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
             key_param_ +
-            "&ext=0&evts=phishcsdhit&"
+            "&ext=0&enh=1&evts=phishcsdhit&"
             "evtd=http%3A%2F%2Fmalicious.url.com%2F&"
             "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer."
             "url.com%2F&evtb=0&src=l4&m=0",
@@ -147,11 +152,12 @@
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = false;
     hp.is_subresource = true;
+    hp.is_enhanced_protection = true;
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
             key_param_ +
-            "&ext=0&evts=malcsdhit&"
+            "&ext=0&enh=1&evts=malcsdhit&"
             "evtd=http%3A%2F%2Fmalicious.url.com%2F&"
             "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer."
             "url.com%2F&evtb=1&src=l4&m=0",
@@ -167,11 +173,12 @@
     hp.is_metrics_reporting_active = false;
     hp.is_subresource = true;
     hp.population_id = "foo bar";
+    hp.is_enhanced_protection = true;
     EXPECT_EQ(
         "https://safebrowsing.google.com/safebrowsing/report?client=unittest&"
         "appver=1.0&pver=4.0" +
             key_param_ +
-            "&ext=0&evts=malcsdhit&"
+            "&ext=0&enh=1&evts=malcsdhit&"
             "evtd=http%3A%2F%2Fmalicious.url.com%2F&"
             "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer."
             "url.com%2F&evtb=1&src=l4&m=0&up=foo+bar",
diff --git a/components/safe_browsing/core/realtime/policy_engine.h b/components/safe_browsing/core/realtime/policy_engine.h
index 8673dbf..685045b 100644
--- a/components/safe_browsing/core/realtime/policy_engine.h
+++ b/components/safe_browsing/core/realtime/policy_engine.h
@@ -25,6 +25,9 @@
 
 // This class implements the logic to decide whether the real time lookup
 // feature is enabled for a given user/profile.
+// TODO(crbug.com/1050859): To make this class build in IOS, remove
+// browser_context dependency in this class, and replace it with pref_service
+// and simple_factory_key.
 class RealTimePolicyEngine {
  public:
   RealTimePolicyEngine() = delete;
diff --git a/components/safe_browsing/core/realtime/url_lookup_service.cc b/components/safe_browsing/core/realtime/url_lookup_service.cc
index de329c95..444bd7c 100644
--- a/components/safe_browsing/core/realtime/url_lookup_service.cc
+++ b/components/safe_browsing/core/realtime/url_lookup_service.cc
@@ -7,6 +7,7 @@
 #include "base/base64url.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_piece.h"
+#include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "components/safe_browsing/core/common/thread_utils.h"
 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
@@ -55,7 +56,7 @@
     RTLookupRequestCallback request_callback,
     RTLookupResponseCallback response_callback,
     signin::IdentityManager* identity_manager) {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
   DCHECK(url.is_valid());
 
   std::unique_ptr<RTLookupRequest> request = FillRequestProto(url);
@@ -114,7 +115,9 @@
 
   pending_requests_[owned_loader.release()] = std::move(response_callback);
 
-  std::move(request_callback).Run(std::move(request));
+  base::PostTask(
+      FROM_HERE, CreateTaskTraits(ThreadID::IO),
+      base::BindOnce(std::move(request_callback), std::move(request)));
 }
 
 void RealTimeUrlLookupService::Shutdown() {
@@ -133,7 +136,7 @@
     network::SimpleURLLoader* url_loader,
     base::TimeTicks request_start_time,
     std::unique_ptr<std::string> response_body) {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
 
   auto it = pending_requests_.find(url_loader);
   DCHECK(it != pending_requests_.end()) << "Request not found";
@@ -153,15 +156,11 @@
                  response->ParseFromString(*response_body);
   success ? HandleLookupSuccess() : HandleLookupError();
 
-  std::move(it->second).Run(std::move(response));
+  base::PostTask(FROM_HERE, CreateTaskTraits(ThreadID::IO),
+                 base::BindOnce(std::move(it->second), std::move(response)));
+
   delete it->first;
   pending_requests_.erase(it);
-
-  // If |database_manager| already released current object and there is no
-  // pending request left, delete itself.
-  if (pending_requests_.empty() && is_self_owned_) {
-    delete this;
-  }
 }
 
 bool RealTimeUrlLookupService::CanCheckUrl(const GURL& url) const {
@@ -202,7 +201,7 @@
 }
 
 void RealTimeUrlLookupService::HandleLookupError() {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
   consecutive_failures_++;
 
   // Any successful lookup clears both |consecutive_failures_| as well as
@@ -236,7 +235,7 @@
 }
 
 void RealTimeUrlLookupService::HandleLookupSuccess() {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
   ResetFailures();
 
   // |did_successful_lookup_since_last_backoff_| is set to true only when we
@@ -245,24 +244,18 @@
 }
 
 bool RealTimeUrlLookupService::IsInBackoffMode() const {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
-  return backoff_timer_.IsRunning();
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
+  bool in_backoff = backoff_timer_.IsRunning();
+  UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.RT.Backoff.State", in_backoff);
+  return in_backoff;
 }
 
 void RealTimeUrlLookupService::ResetFailures() {
-  DCHECK(CurrentlyOnThread(ThreadID::IO));
+  DCHECK(CurrentlyOnThread(ThreadID::UI));
   consecutive_failures_ = 0;
   backoff_timer_.Stop();
 }
 
-void RealTimeUrlLookupService::WaitForPendingRequestsOrDelete() {
-  if (pending_requests_.empty()) {
-    delete this;
-    return;
-  }
-  is_self_owned_ = true;
-}
-
 // static
 SBThreatType RealTimeUrlLookupService::GetSBThreatTypeForRTThreatType(
     RTLookupResponse::ThreatInfo::ThreatType rt_threat_type) {
diff --git a/components/safe_browsing/core/realtime/url_lookup_service.h b/components/safe_browsing/core/realtime/url_lookup_service.h
index db7dd25..eaf5dcfc 100644
--- a/components/safe_browsing/core/realtime/url_lookup_service.h
+++ b/components/safe_browsing/core/realtime/url_lookup_service.h
@@ -37,6 +37,7 @@
 
 // This class implements the logic to decide whether the real time lookup
 // feature is enabled for a given user/profile.
+// TODO(crbug.com/1050859): Add RTLookupService check flow.
 class RealTimeUrlLookupService : public KeyedService {
  public:
   explicit RealTimeUrlLookupService(
@@ -61,10 +62,6 @@
                    RTLookupResponseCallback response_callback,
                    signin::IdentityManager* identity_manager_on_ui);
 
-  // Called by |database_manager| when any profile is destroyed. The current
-  // object will finish all pending requests and delete itself.
-  void WaitForPendingRequestsOrDelete();
-
   // KeyedService:
   // Called before the actual deletion of the object.
   void Shutdown() override;
@@ -74,6 +71,9 @@
   static SBThreatType GetSBThreatTypeForRTThreatType(
       RTLookupResponse::ThreatInfo::ThreatType rt_threat_type);
 
+  // Helper function to return a weak pointer.
+  base::WeakPtr<RealTimeUrlLookupService> GetWeakPtr();
+
  private:
   using PendingRTLookupRequests =
       base::flat_map<network::SimpleURLLoader*, RTLookupResponseCallback>;
@@ -105,9 +105,6 @@
 
   std::unique_ptr<RTLookupRequest> FillRequestProto(const GURL& url);
 
-  // Helper function to return a weak pointer.
-  base::WeakPtr<RealTimeUrlLookupService> GetWeakPtr();
-
   PendingRTLookupRequests pending_requests_;
 
   // Count of consecutive failures to complete URL lookup requests. When it
@@ -129,10 +126,6 @@
   // If this timer is running, backoff is in effect.
   base::OneShotTimer backoff_timer_;
 
-  // Indicates whether this object is self-owned or owned by |database_manager|.
-  // It is self-owned after any one of the profile is destroyed.
-  bool is_self_owned_ = false;
-
   // The URLLoaderFactory we use to issue network requests.
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 8f9811a..0775c97 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -1103,18 +1103,32 @@
     gfx::Rect crop_rect =
         gfx::ToEnclosingRect(rpdq_params.backdrop_filter_bounds->rect());
     SkIRect sk_crop_rect = gfx::RectToSkIRect(crop_rect);
-    // Offsetting (0,0) does nothing to the actual image, but is the most
-    // convenient way to embed the crop rect into the filter DAG.
-    // TODO(michaelludwig) - Remove this once Skia doesn't always auto-expand
-    sk_sp<SkImageFilter> crop =
-        SkImageFilters::Offset(0.0f, 0.0f, nullptr, &sk_crop_rect);
-    backdrop_filter = SkImageFilters::Compose(
-        crop, SkImageFilters::Compose(std::move(backdrop_filter), crop));
-    // Update whether or not a post-filter clear is needed (crop didn't
-    // completely match bounds)
-    post_backdrop_filter_clear_needed |=
-        backdrop_bounds_type != gfx::RRectF::Type::kRect ||
-        gfx::RectF(crop_rect) != rpdq_params.backdrop_filter_bounds->rect();
+
+    SkIRect sk_src_rect = backdrop_filter->filterBounds(
+        sk_crop_rect, SkMatrix::I(), SkImageFilter::kReverse_MapDirection,
+        &sk_crop_rect);
+    if (sk_crop_rect == sk_src_rect) {
+      // The backdrop filter does not "move" pixels, i.e. a pixel's value only
+      // depends on its (x,y) and prior color. Avoid cropping the input in this
+      // case since composing a crop rect into the filter DAG forces Skia to
+      // map the backdrop content into the local space, which can introduce
+      // filtering artifacts: crbug.com/1044032. Instead just post-filter
+      // clearing will achieve the same cropping of the output at higher quality
+      post_backdrop_filter_clear_needed = true;
+    } else {
+      // Offsetting (0,0) does nothing to the actual image, but is the most
+      // convenient way to embed the crop rect into the filter DAG.
+      // TODO(michaelludwig) - Remove this once Skia doesn't always auto-expand
+      sk_sp<SkImageFilter> crop =
+          SkImageFilters::Offset(0.0f, 0.0f, nullptr, &sk_crop_rect);
+      backdrop_filter = SkImageFilters::Compose(
+          crop, SkImageFilters::Compose(std::move(backdrop_filter), crop));
+      // Update whether or not a post-filter clear is needed (crop didn't
+      // completely match bounds)
+      post_backdrop_filter_clear_needed |=
+          backdrop_bounds_type != gfx::RRectF::Type::kRect ||
+          gfx::RectF(crop_rect) != rpdq_params.backdrop_filter_bounds->rect();
+    }
   }
 
   SkRect bounds = gfx::RectFToSkRect(rpdq_params.bypass_clip.has_value()
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 2a2b5ea..0065d2d 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -329,7 +329,6 @@
     owned_sync_point_manager_ = std::make_unique<gpu::SyncPointManager>();
     sync_point_manager = owned_sync_point_manager_.get();
   }
-  sync_point_manager_ = sync_point_manager;
 
   if (!shared_image_manager) {
     // When using real buffers for testing overlay configurations, we need
@@ -344,7 +343,6 @@
     // SharedImageManager.
     DCHECK(!features::ShouldUseRealBuffersForPageFlipTest());
   }
-  shared_image_manager_ = shared_image_manager;
 
   shutdown_event_ = shutdown_event;
   if (!shutdown_event_) {
@@ -355,33 +353,23 @@
   }
 
   scheduler_ = std::make_unique<gpu::Scheduler>(
-      main_runner_, sync_point_manager_, gpu_preferences_);
-
-  default_offscreen_surface_ = std::move(default_offscreen_surface);
-  activity_flags_.emplace(std::move(activity_flags));
+      main_runner_, sync_point_manager, gpu_preferences_);
 
   // Defer creation of the render thread. This is to prevent it from handling
   // IPC messages before the sandbox has been enabled and all other necessary
   // initialization has succeeded.
-  InitializeGpuChannelManager();
-
-  if (watchdog_thread())
-    watchdog_thread()->AddPowerObserver();
-}
-
-void GpuServiceImpl::InitializeGpuChannelManager() {
-  DCHECK(!gpu_channel_manager_ && !media_gpu_channel_manager_);
-
   gpu_channel_manager_ = std::make_unique<gpu::GpuChannelManager>(
       gpu_preferences_, this, watchdog_thread_.get(), main_runner_, io_runner_,
-      scheduler_.get(), sync_point_manager_, shared_image_manager_,
+      scheduler_.get(), sync_point_manager, shared_image_manager,
       gpu_memory_buffer_factory_.get(), gpu_feature_info_,
-      &activity_flags_.value(), default_offscreen_surface_,
+      std::move(activity_flags), std::move(default_offscreen_surface),
       image_decode_accelerator_worker_.get(), vulkan_context_provider(),
       metal_context_provider_.get(), dawn_context_provider());
 
-  media_gpu_channel_manager_ = std::make_unique<media::MediaGpuChannelManager>(
-      gpu_channel_manager_.get());
+  media_gpu_channel_manager_.reset(
+      new media::MediaGpuChannelManager(gpu_channel_manager_.get()));
+  if (watchdog_thread())
+    watchdog_thread()->AddPowerObserver();
 }
 
 void GpuServiceImpl::Bind(
@@ -926,23 +914,9 @@
   }
   DVLOG(1) << "GPU: Performing background cleanup";
   gpu_channel_manager_->OnBackgroundCleanup();
-
-  if (features::IsUsingSkiaRenderer()) {
-    // Release context providers and related on low-end device to save memory.
-    gpu_memory_buffer_factory_.reset();
-#if BUILDFLAG(ENABLE_VULKAN)
-    vulkan_context_provider_.reset();
-#endif
-#if BUILDFLAG(SKIA_USE_DAWN)
-    dawn_context_provider_.reset();
-#endif
-    gpu_channel_manager_.reset();
-    media_gpu_channel_manager_.reset();
-  }
-
-#else   // defined(OS_ANDROID)
+#else
   NOTREACHED();
-#endif  // !defined(OS_ANDROID)
+#endif
 }
 
 void GpuServiceImpl::OnBackgrounded() {
@@ -960,54 +934,8 @@
 }
 
 void GpuServiceImpl::OnForegrounded() {
-  DCHECK(io_runner_->BelongsToCurrentThread());
   if (watchdog_thread_)
     watchdog_thread_->OnForegrounded();
-
-#if defined(OS_ANDROID)
-  if (features::IsUsingSkiaRenderer()) {
-    main_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&GpuServiceImpl::OnForegroundedOnMainThread, weak_ptr_));
-  }
-#endif  // defined(OS_ANDROID)
-}
-
-void GpuServiceImpl::OnForegroundedOnMainThread() {
-#if defined(OS_ANDROID)
-  if (gpu_channel_manager())
-    return;
-  DCHECK(features::IsUsingSkiaRenderer());
-
-#if BUILDFLAG(ENABLE_VULKAN)
-  if (vulkan_implementation_) {
-    size_t max_resource_cache_bytes;
-    size_t max_glyph_cache_texture_bytes;
-    gpu::DetermineGrCacheLimitsFromAvailableMemory(
-        &max_resource_cache_bytes, &max_glyph_cache_texture_bytes);
-    GrContextOptions context_options;
-    context_options.fGlyphCacheTextureMaximumBytes =
-        max_glyph_cache_texture_bytes;
-    if (gpu_preferences_.force_max_texture_size) {
-      context_options.fMaxTextureSizeOverride =
-          gpu_preferences_.force_max_texture_size;
-    }
-    vulkan_context_provider_ = VulkanInProcessContextProvider::Create(
-        vulkan_implementation_, context_options);
-  }
-#endif  // BUILDFLAG(ENABLE_VULKAN)
-
-#if BUILDFLAG(SKIA_USE_DAWN)
-  if (gpu_preferences_.gr_context_type == gpu::GrContextType::kDawn) {
-    dawn_context_provider_ = DawnContextProvider::Create();
-  }
-#endif  // BUILDFLAG(SKIA_USE_DAWN)
-
-  gpu_memory_buffer_factory_ =
-      gpu::GpuMemoryBufferFactory::CreateNativeType(vulkan_context_provider());
-
-  InitializeGpuChannelManager();
-#endif  // defined(OS_ANDROID)
 }
 
 #if !defined(OS_ANDROID)
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h
index 4d9c414..47ce5e5 100644
--- a/components/viz/service/gl/gpu_service_impl.h
+++ b/components/viz/service/gl/gpu_service_impl.h
@@ -313,10 +313,8 @@
 #endif  // defined(OS_CHROMEOS)
 
   void RequestHDRStatusOnMainThread(RequestHDRStatusCallback callback);
-  void InitializeGpuChannelManager();
 
   void OnBackgroundedOnMainThread();
-  void OnForegroundedOnMainThread();
 
   // Ensure that all peak memory tracking occurs on the main thread as all
   // MemoryTracker are created on that thread. All requests made before
@@ -419,12 +417,6 @@
   // Display compositor contexts that don't have a corresponding GPU channel.
   base::ObserverList<gpu::DisplayContext>::Unchecked display_contexts_;
 
-  // Cached resources for recreating |gpu_channel_manager_|.
-  base::Optional<gpu::GpuProcessActivityFlags> activity_flags_;
-  scoped_refptr<gl::GLSurface> default_offscreen_surface_;
-  gpu::SyncPointManager* sync_point_manager_;
-  gpu::SharedImageManager* shared_image_manager_;
-
   base::WeakPtr<GpuServiceImpl> weak_ptr_;
   base::WeakPtrFactory<GpuServiceImpl> weak_ptr_factory_{this};
 
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
index 5f5f7da1..0fe7e120 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -42,6 +42,10 @@
     // remove leading 'UIA_' and trailing 'PropertyId'
     return identifier.substr(4, identifier.size() - 14);
   }
+  if (id >= UIA_ButtonControlTypeId && id <= UIA_AppBarControlTypeId) {
+    // remove leading 'UIA_' and trailing 'ControlTypeId'
+    return identifier.substr(4, identifier.size() - 17);
+  }
   return identifier;
 }
 
@@ -1005,14 +1009,15 @@
   std::unique_ptr<base::DictionaryValue> tree;
   base::string16 line;
 
-  // Always show role, and show it first.
-  base::string16 role_value;
-  dict.GetString(UiaIdentifierToCondensedString(UIA_AriaRolePropertyId),
-                 &role_value);
-  WriteAttribute(true, role_value, &line);
+  // Always show control type, and show it first.
+  base::string16 control_type_value;
+  dict.GetString(UiaIdentifierToCondensedString(UIA_ControlTypePropertyId),
+                 &control_type_value);
+  WriteAttribute(true, control_type_value, &line);
   if (filtered_result) {
     filtered_result->SetString(
-        UiaIdentifierToStringUTF8(UIA_AriaRolePropertyId), role_value);
+        UiaIdentifierToStringUTF8(UIA_ControlTypePropertyId),
+        control_type_value);
   }
 
   // properties
diff --git a/content/browser/devtools/protocol/devtools_download_manager_delegate.cc b/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
index 85a1684..703e01e7 100644
--- a/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
+++ b/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -115,10 +116,9 @@
       &DevToolsDownloadManagerDelegate::OnDownloadPathGenerated,
       base::Unretained(this), item->GetId(), std::move(*callback));
 
-  PostTask(
+  base::ThreadPool::PostTask(
       FROM_HERE,
-      {base::ThreadPool(), base::MayBlock(),
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
        base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&DevToolsDownloadManagerDelegate::GenerateFilename,
                      item->GetURL(), item->GetContentDisposition(),
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 4f63d977..4310f69d 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -727,6 +727,8 @@
     std::move(callback_).Run(nullptr);
   }
 
+  void ResetProxy() { proxy_ = nullptr; }
+
  private:
   class ListenerProxy : public content::FileSelectListener {
    public:
@@ -737,6 +739,8 @@
           << "Should call either FileSelectListener::FileSelected() or "
              "FileSelectListener::FileSelectionCanceled()";
 #endif
+      if (owner_)
+        owner_->ResetProxy();
     }
     void ResetOwner() { owner_ = nullptr; }
 
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index 3a1cd1bd..3dc21b2 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -12,7 +12,6 @@
 #include "base/numerics/safe_math.h"
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "content/browser/bad_message.h"
 #include "content/browser/indexed_db/indexed_db_callback_helpers.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 711299d..dd02346 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -46,7 +46,6 @@
 #include "content/browser/indexed_db/indexed_db_reporting.h"
 #include "content/browser/indexed_db/indexed_db_tracing.h"
 #include "content/browser/indexed_db/indexed_db_value.h"
-#include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -2747,13 +2746,13 @@
   if (!ObjectStoreCursorOptions(leveldb_transaction, database_id,
                                 object_store_id, range, direction,
                                 &cursor_options, s)) {
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
   }
   std::unique_ptr<ObjectStoreCursorImpl> cursor(
       std::make_unique<ObjectStoreCursorImpl>(transaction->AsWeakPtr(),
                                               database_id, cursor_options));
   if (!cursor->FirstSeek(s))
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
 
   return std::move(cursor);
 }
@@ -2776,13 +2775,13 @@
   if (!ObjectStoreCursorOptions(leveldb_transaction, database_id,
                                 object_store_id, range, direction,
                                 &cursor_options, s)) {
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
   }
   std::unique_ptr<ObjectStoreKeyCursorImpl> cursor(
       std::make_unique<ObjectStoreKeyCursorImpl>(transaction->AsWeakPtr(),
                                                  database_id, cursor_options));
   if (!cursor->FirstSeek(s))
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
 
   return std::move(cursor);
 }
@@ -2805,12 +2804,12 @@
   cursor_options.mode = transaction->mode();
   if (!IndexCursorOptions(leveldb_transaction, database_id, object_store_id,
                           index_id, range, direction, &cursor_options, s))
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
   std::unique_ptr<IndexKeyCursorImpl> cursor(
       std::make_unique<IndexKeyCursorImpl>(transaction->AsWeakPtr(),
                                            database_id, cursor_options));
   if (!cursor->FirstSeek(s))
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
 
   return std::move(cursor);
 }
@@ -2832,11 +2831,11 @@
   cursor_options.mode = transaction->mode();
   if (!IndexCursorOptions(leveldb_transaction, database_id, object_store_id,
                           index_id, range, direction, &cursor_options, s))
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
   std::unique_ptr<IndexCursorImpl> cursor(new IndexCursorImpl(
       transaction->AsWeakPtr(), database_id, cursor_options));
   if (!cursor->FirstSeek(s))
-    return std::unique_ptr<IndexedDBBackingStore::Cursor>();
+    return nullptr;
 
   return std::move(cursor);
 }
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc
index fbd09db..d673d49 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -16,7 +16,6 @@
 #include "base/task/post_task.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
-#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/indexed_db/cursor_impl.h"
 #include "content/browser/indexed_db/database_impl.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
@@ -26,8 +25,6 @@
 #include "content/browser/indexed_db/indexed_db_return_value.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "content/browser/indexed_db/indexed_db_value.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "storage/browser/quota/quota_manager.h"
 #include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
index ff44a1ff..635b13b 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -22,7 +22,6 @@
 #include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "components/services/storage/public/mojom/indexed_db_control_test.mojom.h"
 #include "components/services/storage/public/mojom/native_file_system_context.mojom.h"
-#include "content/browser/browser_main_loop.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index dd634124..cc106a7 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -20,7 +20,6 @@
 #include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h"
 #include "content/browser/indexed_db/indexed_db_external_object.h"
 #include "content/common/content_export.h"
-#include "content/public/browser/render_process_host_observer.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
diff --git a/content/browser/indexed_db/indexed_db_quota_client.cc b/content/browser/indexed_db/indexed_db_quota_client.cc
index 38b2b83..df6138c 100644
--- a/content/browser/indexed_db/indexed_db_quota_client.cc
+++ b/content/browser/indexed_db/indexed_db_quota_client.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/task/post_task.h"
+#include "base/task_runner_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "net/base/url_util.h"
diff --git a/content/browser/loader/quic_transport_browsertest.cc b/content/browser/loader/quic_transport_browsertest.cc
index a652e521..21d07af 100644
--- a/content/browser/loader/quic_transport_browsertest.cc
+++ b/content/browser/loader/quic_transport_browsertest.cc
@@ -103,8 +103,9 @@
         switches::kOriginToForceQuicOn,
         base::StringPrintf("localhost:%d", server_.server_address().port()));
     command_line->AppendSwitch(switches::kEnableQuic);
+    // TODO(crbug.com/1055027): Don't hardcode the ALPN string.
     command_line->AppendSwitchASCII(switches::kQuicVersion,
-                                    base::StringPrintf("h3-25"));
+                                    base::StringPrintf("h3-26"));
     // The value is calculated from net/data/ssl/certificates/quic-chain.pem.
     command_line->AppendSwitchASCII(
         network::switches::kIgnoreCertificateErrorsSPKIList,
diff --git a/content/browser/renderer_host/frame_token_message_queue.cc b/content/browser/renderer_host/frame_token_message_queue.cc
index ba69284b..a48ea52 100644
--- a/content/browser/renderer_host/frame_token_message_queue.cc
+++ b/content/browser/renderer_host/frame_token_message_queue.cc
@@ -5,6 +5,9 @@
 #include "content/browser/renderer_host/frame_token_message_queue.h"
 
 #include "base/bind.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/strings/string_number_conversions.h"
 #include "ipc/ipc_message.h"
 
 namespace content {
@@ -20,6 +23,18 @@
 void FrameTokenMessageQueue::DidProcessFrame(uint32_t frame_token) {
   // Frame tokens always increase.
   if (frame_token <= last_received_frame_token_) {
+    // TODO(samans): Remove this once the investigation into
+    // https://crbug.com/1045372 is over.
+    static auto* last_frame_token = base::debug::AllocateCrashKeyString(
+        "last_frame_token", base::debug::CrashKeySize::Size32);
+    static auto* new_frame_token = base::debug::AllocateCrashKeyString(
+        "new_frame_token", base::debug::CrashKeySize::Size32);
+    base::debug::SetCrashKeyString(
+        last_frame_token, base::NumberToString(last_received_frame_token_));
+    base::debug::SetCrashKeyString(new_frame_token,
+                                   base::NumberToString(frame_token));
+    base::debug::DumpWithoutCrashing();
+
     client_->OnInvalidFrameToken(frame_token);
     return;
   }
@@ -58,6 +73,11 @@
 void FrameTokenMessageQueue::OnFrameSwapMessagesReceived(
     uint32_t frame_token,
     std::vector<IPC::Message> messages) {
+  // TODO(samans): Remove this once the investigation into
+  // https://crbug.com/1045372 is over.
+  if (!frame_token) {
+    base::debug::DumpWithoutCrashing();
+  }
   EnqueueOrRunFrameTokenCallback(
       frame_token, base::BindOnce(&FrameTokenMessageQueue::ProcessSwapMessages,
                                   base::Unretained(this), std::move(messages)));
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 072c976..0f611e2 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -15,6 +15,7 @@
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/task_runner_util.h"
 #include "base/trace_event/trace_event.h"
 #include "components/services/storage/public/cpp/constants.h"
@@ -1571,10 +1572,8 @@
   // TODO(nhiroki): What if there is a bunch of files in the cache directory?
   // Deleting the directory could take a long time and restart could be delayed.
   // We should probably rename the directory and delete it later.
-  PostTaskAndReplyWithResult(
-      FROM_HERE,
-      {base::ThreadPool(), base::MayBlock(),
-       base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
       base::BindOnce(&base::DeleteFileRecursively, GetDiskCachePath()),
       base::BindOnce(&ServiceWorkerStorage::DidDeleteDiskCache,
                      weak_factory_.GetWeakPtr(), std::move(callback)));
diff --git a/content/browser/webrtc/webrtc_content_browsertest_base.cc b/content/browser/webrtc/webrtc_content_browsertest_base.cc
index 043945e..741087b 100644
--- a/content/browser/webrtc/webrtc_content_browsertest_base.cc
+++ b/content/browser/webrtc/webrtc_content_browsertest_base.cc
@@ -31,6 +31,12 @@
     base::CommandLine* command_line) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnforceWebRtcIPPermissionCheck);
+#if defined(OS_LINUX)
+  // Due to problems with PulseAudio failing to start, use a fake audio
+  // stream. crbug.com/1047655#c70
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kDisableAudioOutput);
+#endif
 
   // Loopback interface is the non-default local address. They should only be in
   // the candidate list if the ip handling policy is "default" AND the media
diff --git a/content/public/common/OWNERS b/content/public/common/OWNERS
index ff6e095..4362385 100644
--- a/content/public/common/OWNERS
+++ b/content/public/common/OWNERS
@@ -12,3 +12,5 @@
 per-file *.typemap=file://ipc/SECURITY_OWNERS
 per-file *_type_converter*.*=set noparent
 per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
+per-file sandbox*=set noparent
+per-file sandbox*=file://sandbox/OWNERS
diff --git a/content/public/common/sandboxed_process_launcher_delegate.cc b/content/public/common/sandboxed_process_launcher_delegate.cc
index 074a0777..ee8e819d 100644
--- a/content/public/common/sandboxed_process_launcher_delegate.cc
+++ b/content/public/common/sandboxed_process_launcher_delegate.cc
@@ -34,7 +34,9 @@
 
 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
 service_manager::ZygoteHandle SandboxedProcessLauncherDelegate::GetZygote() {
-  return nullptr;
+  // Default to the sandboxed zygote. If a more lax sandbox is needed, then the
+  // child class should override this method and use the unsandboxed zygote.
+  return service_manager::GetGenericZygote();
 }
 #endif  // BUILDFLAG(USE_ZYGOTE_HANDLE)
 
diff --git a/content/public/common/sandboxed_process_launcher_delegate.h b/content/public/common/sandboxed_process_launcher_delegate.h
index f02a2e9..9d7fd9c 100644
--- a/content/public/common/sandboxed_process_launcher_delegate.h
+++ b/content/public/common/sandboxed_process_launcher_delegate.h
@@ -43,8 +43,6 @@
 
 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
   // Returns the zygote used to launch the process.
-  // NOTE: For now Chrome always uses the same zygote for performance reasons.
-  // http://crbug.com/569191
   virtual service_manager::ZygoteHandle GetZygote();
 #endif  // BUILDFLAG(USE_ZYGOTE_HANDLE)
 
diff --git a/content/public/test/no_renderer_crashes_assertion.cc b/content/public/test/no_renderer_crashes_assertion.cc
index 5d93bb7..5b3d099 100644
--- a/content/public/test/no_renderer_crashes_assertion.cc
+++ b/content/public/test/no_renderer_crashes_assertion.cc
@@ -88,9 +88,20 @@
       break;  // Crash - need to trigger a test failure below.
   }
 
-  FAIL() << "Unexpected termination of a renderer process"
-         << "; status: " << process_info->status
-         << ", exit_code: " << process_info->exit_code;
+  const auto exit_code = process_info->exit_code;
+  // Windows error codes such as 0xC0000005 and 0xC0000409 are much easier
+  // to recognize and differentiate in hex.
+  if (static_cast<int>(exit_code) < -100) {
+    FAIL() << "Unexpected termination of a renderer process"
+           << "; status: " << process_info->status << ", exit_code: 0x"
+           << std::hex << exit_code;
+  } else {
+    // Print other error codes as a signed integer so that small negative
+    // numbers are also recognizable.
+    FAIL() << "Unexpected termination of a renderer process"
+           << "; status: " << process_info->status
+           << ", exit_code: " << exit_code;
+  }
 }
 
 ScopedAllowRendererCrashes::ScopedAllowRendererCrashes()
diff --git a/content/shell/browser/shell_download_manager_delegate.cc b/content/shell/browser/shell_download_manager_delegate.cc
index f104513..7d53046 100644
--- a/content/shell/browser/shell_download_manager_delegate.cc
+++ b/content/shell/browser/shell_download_manager_delegate.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "build/build_config.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -85,15 +86,15 @@
       &ShellDownloadManagerDelegate::OnDownloadPathGenerated,
       weak_ptr_factory_.GetWeakPtr(), download->GetId(), std::move(*callback));
 
-  PostTask(FROM_HERE,
-           {base::ThreadPool(), base::MayBlock(),
-            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
-            base::TaskPriority::USER_VISIBLE},
-           base::BindOnce(&ShellDownloadManagerDelegate::GenerateFilename,
-                          download->GetURL(), download->GetContentDisposition(),
-                          download->GetSuggestedFilename(),
-                          download->GetMimeType(), default_download_path_,
-                          std::move(filename_determined_callback)));
+  base::ThreadPool::PostTask(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+       base::TaskPriority::USER_VISIBLE},
+      base::BindOnce(&ShellDownloadManagerDelegate::GenerateFilename,
+                     download->GetURL(), download->GetContentDisposition(),
+                     download->GetSuggestedFilename(), download->GetMimeType(),
+                     default_download_path_,
+                     std::move(filename_determined_callback)));
   return true;
 }
 
diff --git a/content/test/data/accessibility/aria/annotation-roles-expected-uia-win.txt b/content/test/data/accessibility/aria/annotation-roles-expected-uia-win.txt
index 1e2c73559..a1889b7 100644
--- a/content/test/data/accessibility/aria/annotation-roles-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/annotation-roles-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document LocalizedControlType='document'
-++group Name='comment'
-++group Name='suggestion'
-++group LocalizedControlType='group' IsControlElement=false
-++++description Name='This is '
-++++description LocalizedControlType='highlight'
-++++++description Name='highlighted'
-++++description Name='.'
+Document LocalizedControlType='document'
+++Name='comment'
+++Name='suggestion'
+++Group LocalizedControlType='group' IsControlElement=false
+++++Text Name='This is '
+++++Text LocalizedControlType='highlight'
+++++++Text Name='highlighted'
+++++Text Name='.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-button-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-button-expected-uia-win.txt
index e9a295af..bba71c2 100644
--- a/content/test/data/accessibility/aria/aria-button-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-button-expected-uia-win.txt
@@ -1,16 +1,16 @@
-document
-++button Name='Button1'
-++button Name='Button2' Toggle.ToggleState='On'
-++button Name='Button3' Toggle.ToggleState='Off'
-++button Name='Button4' ExpandCollapse.ExpandCollapseState='Collapsed'
-++button Name='Button5'
-++button Name='Complex button '
-++++description Name='Complex button ' IsControlElement=false
-++++textbox
-++button Name='Complex toggle button ' Toggle.ToggleState='On'
-++++description Name='Complex toggle button '
-++++textbox
-++button Name='Complex pop up button ' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++description Name='Complex pop up button '
-++++textbox
+Document
+++Button Name='Button1'
+++Button Name='Button2' Toggle.ToggleState='On'
+++Button Name='Button3' Toggle.ToggleState='Off'
+++Button Name='Button4' ExpandCollapse.ExpandCollapseState='Collapsed'
+++Button Name='Button5'
+++Button Name='Complex button '
+++++Text Name='Complex button ' IsControlElement=false
+++++Edit
+++Button Name='Complex toggle button ' Toggle.ToggleState='On'
+++++Text Name='Complex toggle button '
+++++Edit
+++Button Name='Complex pop up button ' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++Text Name='Complex pop up button '
+++++Edit
 <-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-code-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-code-expected-uia-win.txt
index 82c07ef..b676cf7 100644
--- a/content/test/data/accessibility/aria/aria-code-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-code-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document LocalizedControlType='document'
-++code LocalizedControlType='code'
-++++description LocalizedControlType='text' Name='role'
-++description LocalizedControlType='text' Name='element (no name)'
-++description LocalizedControlType='text' Name=' '
-++code LocalizedControlType='code' Name='include me'
-++++description LocalizedControlType='text' Name='element (with name)'
+Document LocalizedControlType='document'
+++Text LocalizedControlType='code'
+++++Text LocalizedControlType='text' Name='role'
+++Text LocalizedControlType='text' Name='element (no name)'
+++Text LocalizedControlType='text' Name=' '
+++Text LocalizedControlType='code' Name='include me'
+++++Text LocalizedControlType='text' Name='element (with name)'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win.txt
index 99519c3c..0765bdf4 100644
--- a/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++contentinfo LocalizedControlType='content information' LocalizedLandmarkType='content information'
-++++description Name='This is ARIA role contentinfo.'
+Document
+++Group LocalizedControlType='content information' LocalizedLandmarkType='content information'
+++++Text Name='This is ARIA role contentinfo.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win7.txt b/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win7.txt
index 4a188f5..d9d968e6 100644
--- a/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win7.txt
+++ b/content/test/data/accessibility/aria/aria-contentinfo-expected-uia-win7.txt
@@ -1,3 +1,4 @@
-document
-++contentinfo LocalizedControlType='content information'
-++++description Name='This is ARIA role contentinfo.'
+Document
+++Group LocalizedControlType='content information'
+++++Text Name='This is ARIA role contentinfo.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-emphasis-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-emphasis-expected-uia-win.txt
index 97d1321..13e36bdb 100644
--- a/content/test/data/accessibility/aria/aria-emphasis-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-emphasis-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document LocalizedControlType='document'
-++emphasis LocalizedControlType='emphasis'
-++++description LocalizedControlType='text' Name='role'
-++description LocalizedControlType='text' Name='element (no name)'
-++description LocalizedControlType='text' Name=' '
-++emphasis LocalizedControlType='emphasis' Name='include me'
-++++description LocalizedControlType='text' Name='element (with name)'
+Document LocalizedControlType='document'
+++Text LocalizedControlType='emphasis'
+++++Text LocalizedControlType='text' Name='role'
+++Text LocalizedControlType='text' Name='element (no name)'
+++Text LocalizedControlType='text' Name=' '
+++Text LocalizedControlType='emphasis' Name='include me'
+++++Text LocalizedControlType='text' Name='element (with name)'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-generic-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-generic-expected-uia-win.txt
index abe00ed..7b2c656 100644
--- a/content/test/data/accessibility/aria/aria-generic-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-generic-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group
-++++description Name='content'
+Document
+++Group
+++++Text Name='content'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-gridcell-focused-only-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-gridcell-focused-only-expected-uia-win.txt
index e1f394ad..1b14abe 100644
--- a/content/test/data/accessibility/aria/aria-gridcell-focused-only-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-gridcell-focused-only-expected-uia-win.txt
@@ -1,13 +1,14 @@
-document
-++grid Grid.ColumnCount=2 Grid.RowCount=2 Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false Table.RowOrColumnMajor='RowMajor'
-++++row
-++++++columnheader Name='Browser' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='Browser' IsControlElement=false
-++++++columnheader Name='Rendering Engine' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='Rendering Engine' IsControlElement=false
-++++row
-++++++gridcell Name='Chrome' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='Chrome' IsControlElement=false
-++++++gridcell Name='Blink' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='Blink' IsControlElement=false
-++description Name='Done'
+Document
+++DataGrid Grid.ColumnCount=2 Grid.RowCount=2 Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false Table.RowOrColumnMajor='RowMajor'
+++++DataItem
+++++++DataItem Name='Browser' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='Browser' IsControlElement=false
+++++++DataItem Name='Rendering Engine' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='Rendering Engine' IsControlElement=false
+++++DataItem
+++++++DataItem Name='Chrome' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='Chrome' IsControlElement=false
+++++++DataItem Name='Blink' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='Blink' IsControlElement=false
+++Text Name='Done'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-hidden-described-by-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-hidden-described-by-expected-uia-win.txt
index 7b60949..e3c48954 100644
--- a/content/test/data/accessibility/aria/aria-hidden-described-by-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-hidden-described-by-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group Name='span-A' DescribedBy='span-1'
-++group Name='span-B' DescribedBy='span-2'
-++group Name='span-C' DescribedBy='span-3'
-++group Name='span-D' DescribedBy='span-4'
+Document
+++Group Name='span-A' DescribedBy='span-1'
+++Group Name='span-B' DescribedBy='span-2'
+++Group Name='span-C' DescribedBy='span-3'
+++Group Name='span-D' DescribedBy='span-4'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-uia-win.txt
index 9c98f7cf..1423b9bb 100644
--- a/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++group Name='span-2'
-++group Name='span-4' LabeledBy='span-4'
-++group Name='span-1' LabeledBy='span-1'
-++group Name='span-2' LabeledBy='span-2'
-++group Name='span-3' LabeledBy='span-4'
-++group Name='span-4' LabeledBy='span-4'
+Document
+++Group Name='span-2'
+++Group Name='span-4' LabeledBy='span-4'
+++Group Name='span-1' LabeledBy='span-1'
+++Group Name='span-2' LabeledBy='span-2'
+++Group Name='span-3' LabeledBy='span-4'
+++Group Name='span-4' LabeledBy='span-4'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-strong-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-strong-expected-uia-win.txt
index 81f7508..d429537 100644
--- a/content/test/data/accessibility/aria/aria-strong-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-strong-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document LocalizedControlType='document'
-++strong LocalizedControlType='strong'
-++++description LocalizedControlType='text' Name='role'
-++description LocalizedControlType='text' Name='element (no name)'
-++description LocalizedControlType='text' Name=' '
-++strong LocalizedControlType='strong' Name='include me'
-++++description LocalizedControlType='text' Name='element (with name)'
+Document LocalizedControlType='document'
+++Text LocalizedControlType='strong'
+++++Text LocalizedControlType='text' Name='role'
+++Text LocalizedControlType='text' Name='element (no name)'
+++Text LocalizedControlType='text' Name=' '
+++Text LocalizedControlType='strong' Name='include me'
+++++Text LocalizedControlType='text' Name='element (with name)'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-time-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-time-expected-uia-win.txt
index cf6a0b92..2e4ed51 100644
--- a/content/test/data/accessibility/aria/aria-time-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-time-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document LocalizedControlType='document'
-++time LocalizedControlType='time'
-++++description LocalizedControlType='text' Name='role'
-++time LocalizedControlType='time'
-++++description LocalizedControlType='text' Name='element (no name)'
-++description LocalizedControlType='text' Name=' '
-++time LocalizedControlType='time' Name='include me'
-++++description LocalizedControlType='text' Name='element (with name)'
+Document LocalizedControlType='document'
+++Text LocalizedControlType='time'
+++++Text LocalizedControlType='text' Name='role'
+++Text LocalizedControlType='time'
+++++Text LocalizedControlType='text' Name='element (no name)'
+++Text LocalizedControlType='text' Name=' '
+++Text LocalizedControlType='time' Name='include me'
+++++Text LocalizedControlType='text' Name='element (with name)'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win.txt b/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win.txt
index e7a15fe..93c4b8d 100644
--- a/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document PositionInSet=0 SizeOfSet=0
-++tree PositionInSet=0 SizeOfSet=2 Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++treeitem Name='card content' PositionInSet=1 SizeOfSet=2 ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='card content' IsControlElement=false PositionInSet=0 SizeOfSet=0
-++++group PositionInSet=0 SizeOfSet=0
-++++treeitem Name='card content' PositionInSet=2 SizeOfSet=2 ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='card content' IsControlElement=false PositionInSet=0 SizeOfSet=0
+Document PositionInSet=0 SizeOfSet=0
+++Tree PositionInSet=0 SizeOfSet=2 Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++TreeItem Name='card content' PositionInSet=1 SizeOfSet=2 ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='card content' IsControlElement=false PositionInSet=0 SizeOfSet=0
+++++Group PositionInSet=0 SizeOfSet=0
+++++TreeItem Name='card content' PositionInSet=2 SizeOfSet=2 ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='card content' IsControlElement=false PositionInSet=0 SizeOfSet=0
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win7.txt b/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win7.txt
index 0d98fa9..02ecc25 100644
--- a/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win7.txt
+++ b/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-uia-win7.txt
@@ -1,7 +1,8 @@
-document
-++tree Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++treeitem Name='card content' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='card content' IsControlElement=false
-++++group
-++++treeitem Name='card content' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='card content' IsControlElement=false
\ No newline at end of file
+Document
+++Tree Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++TreeItem Name='card content' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='card content' IsControlElement=false
+++++Group
+++++TreeItem Name='card content' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='card content' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/hidden-described-by-expected-uia-win.txt b/content/test/data/accessibility/aria/hidden-described-by-expected-uia-win.txt
index 9d3a6a6..b5f9193 100644
--- a/content/test/data/accessibility/aria/hidden-described-by-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/hidden-described-by-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group Name='span-A3' DescribedBy='span-A4'
-++group Name='span-B' DescribedBy='span-A2'
-++group Name='span-C'
+Document
+++Group Name='span-A3' DescribedBy='span-A4'
+++Group Name='span-B' DescribedBy='span-A2'
+++Group Name='span-C'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/hidden-expected-uia-win.txt b/content/test/data/accessibility/aria/hidden-expected-uia-win.txt
index ef2fe77..923230f8 100644
--- a/content/test/data/accessibility/aria/hidden-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/hidden-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group Name='b'
-++group Name='c'
+Document
+++Group Name='b'
+++Group Name='c'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/aria/hidden-labelled-by-expected-uia-win.txt b/content/test/data/accessibility/aria/hidden-labelled-by-expected-uia-win.txt
index e162d4d..52d2557c 100644
--- a/content/test/data/accessibility/aria/hidden-labelled-by-expected-uia-win.txt
+++ b/content/test/data/accessibility/aria/hidden-labelled-by-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group Name='span-A4' LabeledBy='span-A4'
-++group Name='span-A2' LabeledBy='span-A2'
-++group Name='span-C'
+Document
+++Group Name='span-A4' LabeledBy='span-A4'
+++Group Name='span-A2' LabeledBy='span-A2'
+++Group Name='span-C'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/css/transform-expected-uia-win.txt b/content/test/data/accessibility/css/transform-expected-uia-win.txt
index 3c3072e..572f77a 100644
--- a/content/test/data/accessibility/css/transform-expected-uia-win.txt
+++ b/content/test/data/accessibility/css/transform-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false
-++++group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false
-++++++description BoundingRectangle=(0, 50, 48, 17) Name='content'
+Document
+++Group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false
+++++Group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false
+++++++Text BoundingRectangle=(0, 50, 48, 17) Name='content'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/css/visibility-expected-uia-win.txt b/content/test/data/accessibility/css/visibility-expected-uia-win.txt
index 2feaa10..68486b2 100644
--- a/content/test/data/accessibility/css/visibility-expected-uia-win.txt
+++ b/content/test/data/accessibility/css/visibility-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++description Name='visible link'
-++description Name='visible link'
+Document
+++Text Name='visible link'
+++Text Name='visible link'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/a-expected-uia-win.txt b/content/test/data/accessibility/html/a-expected-uia-win.txt
index 77a2856..8bc3713 100644
--- a/content/test/data/accessibility/html/a-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/a-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++link Name='normal link'
-++++++description Name='normal link' IsControlElement=false
+Document
+++Group IsControlElement=false
+++++Hyperlink Name='normal link'
+++++++Text Name='normal link' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/a-name-calc-expected-uia-win.txt b/content/test/data/accessibility/html/a-name-calc-expected-uia-win.txt
index eab7ecec..9d86ffb 100644
--- a/content/test/data/accessibility/html/a-name-calc-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/a-name-calc-expected-uia-win.txt
@@ -1,15 +1,16 @@
-document
-++link Name='InnerText0'
-++++description Name='InnerText0' IsControlElement=false
-++description Name=' '
-++link Name='InnerText1' FullDescription='Title1'
-++++description Name='InnerText1' IsControlElement=false
-++description Name=' '
-++link Name='Title2'
-++++description Name='InnerText2' IsControlElement=false
-++description Name=' '
-++link Name='LabelledBy3'
-++++description Name='InnerText3' IsControlElement=false
-++link Name='Title4'
-++link Name='Label5'
-++link Name='LabelledBy6'
+Document
+++Hyperlink Name='InnerText0'
+++++Text Name='InnerText0' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='InnerText1' FullDescription='Title1'
+++++Text Name='InnerText1' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Title2'
+++++Text Name='InnerText2' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='LabelledBy3'
+++++Text Name='InnerText3' IsControlElement=false
+++Hyperlink Name='Title4'
+++Hyperlink Name='Label5'
+++Hyperlink Name='LabelledBy6'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/a-name-calc-expected-uia-win7.txt b/content/test/data/accessibility/html/a-name-calc-expected-uia-win7.txt
index 6fad4454..3329f62 100644
--- a/content/test/data/accessibility/html/a-name-calc-expected-uia-win7.txt
+++ b/content/test/data/accessibility/html/a-name-calc-expected-uia-win7.txt
@@ -1,15 +1,16 @@
-document
-++link Name='InnerText0'
-++++description Name='InnerText0' IsControlElement=false
-++description Name=' '
-++link Name='InnerText1'
-++++description Name='InnerText1' IsControlElement=false
-++description Name=' '
-++link Name='Title2'
-++++description Name='InnerText2' IsControlElement=false
-++description Name=' '
-++link Name='LabelledBy3'
-++++description Name='InnerText3' IsControlElement=false
-++link Name='Title4'
-++link Name='Label5'
-++link Name='LabelledBy6'
\ No newline at end of file
+Document
+++Hyperlink Name='InnerText0'
+++++Text Name='InnerText0' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='InnerText1'
+++++Text Name='InnerText1' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Title2'
+++++Text Name='InnerText2' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='LabelledBy3'
+++++Text Name='InnerText3' IsControlElement=false
+++Hyperlink Name='Title4'
+++Hyperlink Name='Label5'
+++Hyperlink Name='LabelledBy6'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/a-name-expected-uia-win.txt b/content/test/data/accessibility/html/a-name-expected-uia-win.txt
index 2d0e3e5..d527391e 100644
--- a/content/test/data/accessibility/html/a-name-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/a-name-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++link Name='named anchor'
-++++description Name='named anchor'
-++link Name='both a named anchor and a link'
-++++description Name='both a named anchor and a link' IsControlElement=false
+Document
+++Hyperlink Name='named anchor'
+++++Text Name='named anchor'
+++Hyperlink Name='both a named anchor and a link'
+++++Text Name='both a named anchor and a link' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/a-onclick-expected-uia-win.txt b/content/test/data/accessibility/html/a-onclick-expected-uia-win.txt
index 41f051332..1699f6a 100644
--- a/content/test/data/accessibility/html/a-onclick-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/a-onclick-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++link Name='link with no href but onclick'
-++++description Name='link with no href but onclick' IsControlElement=false
-++link Name='link with no href and click handler added via script'
-++++description Name='link with no href and click handler added via script' IsControlElement=false
+Document
+++Hyperlink Name='link with no href but onclick'
+++++Text Name='link with no href but onclick' IsControlElement=false
+++Hyperlink Name='link with no href and click handler added via script'
+++++Text Name='link with no href and click handler added via script' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/a-with-img-expected-uia-win.txt b/content/test/data/accessibility/html/a-with-img-expected-uia-win.txt
index 8e61a15..8036d5d 100644
--- a/content/test/data/accessibility/html/a-with-img-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/a-with-img-expected-uia-win.txt
@@ -1,19 +1,20 @@
-document
-++group IsControlElement=false
-++++link Name='Link with image at start.'
-++++++img Name='Link'
-++++++description Name=' with image at start.' IsControlElement=false
-++++description Name=' '
-++++link Name='Link with image in the middle.'
-++++++description Name='Link with ' IsControlElement=false
-++++++img Name='image'
-++++++description Name=' in the middle.' IsControlElement=false
-++++description Name=' '
-++++link Name='Link with broken in the middle.'
-++++++description Name='Link with ' IsControlElement=false
-++++++img Name='broken'
-++++++description Name=' in the middle.' IsControlElement=false
-++++description Name=' '
-++++link Name='Link with image at the end'
-++++++description Name='Link with image at the ' IsControlElement=false
-++++++img Name='end'
+Document
+++Group IsControlElement=false
+++++Hyperlink Name='Link with image at start.'
+++++++Image Name='Link'
+++++++Text Name=' with image at start.' IsControlElement=false
+++++Text Name=' '
+++++Hyperlink Name='Link with image in the middle.'
+++++++Text Name='Link with ' IsControlElement=false
+++++++Image Name='image'
+++++++Text Name=' in the middle.' IsControlElement=false
+++++Text Name=' '
+++++Hyperlink Name='Link with broken in the middle.'
+++++++Text Name='Link with ' IsControlElement=false
+++++++Image Name='broken'
+++++++Text Name=' in the middle.' IsControlElement=false
+++++Text Name=' '
+++++Hyperlink Name='Link with image at the end'
+++++++Text Name='Link with image at the ' IsControlElement=false
+++++++Image Name='end'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/abbr-expected-uia-win.txt b/content/test/data/accessibility/html/abbr-expected-uia-win.txt
index 48e920f..6b673dac 100644
--- a/content/test/data/accessibility/html/abbr-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/abbr-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++description Name='The '
-++++description Name='World Health Organization'
-++++++description Name='WHO'
-++++description Name=' was founded in 1948.'
+Document
+++Group IsControlElement=false
+++++Text Name='The '
+++++Text Name='World Health Organization'
+++++++Text Name='WHO'
+++++Text Name=' was founded in 1948.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/action-verbs-expected-uia-win.txt b/content/test/data/accessibility/html/action-verbs-expected-uia-win.txt
index fb050b49..84529d4c 100644
--- a/content/test/data/accessibility/html/action-verbs-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/action-verbs-expected-uia-win.txt
@@ -1,36 +1,37 @@
-document Name='Action verbs'
-++group IsControlElement=false
-++++description Name='Generic div'
-++heading Name='Heading'
-++++description Name='Heading' IsControlElement=false
-++button Name='Button'
-++link Name='Link'
-++++description Name='Link' IsControlElement=false
-++textbox
-++searchbox
-++textbox
-++textbox
-++checkbox Toggle.ToggleState='Off'
-++checkbox Toggle.ToggleState='On'
-++radio SelectionItem.IsSelected=false
-++switch Name='ARIA Switch' Toggle.ToggleState='Off'
-++group
-++++button Name='Summary' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++++description Name='Summary'
-++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Pop-up button'
-++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++listitem Name='Pop-up button' SelectionItem.IsSelected=true
-++group
-++++description Name='Div with click handler'
-++group
-++++group IsControlElement=false
-++++++description Name='Paragraph with click handler on parent' IsControlElement=false
-++menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++menuitem Name='Menu item 1'
-++++menuitemcheckbox Name='Menu item 2' Toggle.ToggleState='On'
-++++menuitemradio Name='Menu item 3' SelectionItem.IsSelected=false
-++button Name='ARIA Button'
-++button Name='ARIA button with tab index'
-++button Name='ARIA button with negative tab index'
-++group
-++++button Name='ARIA button that is an active descendant'
+Document Name='Action verbs'
+++Group IsControlElement=false
+++++Text Name='Generic div'
+++Text Name='Heading'
+++++Text Name='Heading' IsControlElement=false
+++Button Name='Button'
+++Hyperlink Name='Link'
+++++Text Name='Link' IsControlElement=false
+++Edit
+++Edit
+++Edit
+++Edit
+++CheckBox Toggle.ToggleState='Off'
+++CheckBox Toggle.ToggleState='On'
+++RadioButton SelectionItem.IsSelected=false
+++Button Name='ARIA Switch' Toggle.ToggleState='Off'
+++Group
+++++Button Name='Summary' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++++Text Name='Summary'
+++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Pop-up button'
+++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++ListItem Name='Pop-up button' SelectionItem.IsSelected=true
+++Group
+++++Text Name='Div with click handler'
+++Group
+++++Group IsControlElement=false
+++++++Text Name='Paragraph with click handler on parent' IsControlElement=false
+++Menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++MenuItem Name='Menu item 1'
+++++CheckBox Name='Menu item 2' Toggle.ToggleState='On'
+++++RadioButton Name='Menu item 3' SelectionItem.IsSelected=false
+++Button Name='ARIA Button'
+++Button Name='ARIA button with tab index'
+++Button Name='ARIA button with negative tab index'
+++Group
+++++Button Name='ARIA button that is an active descendant'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/actions-expected-uia-win.txt b/content/test/data/accessibility/html/actions-expected-uia-win.txt
index b542d3b..02dad7ee 100644
--- a/content/test/data/accessibility/html/actions-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/actions-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document Name='Actions'
-++group IsControlElement=false
-++++slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=100.00 RangeValue.Minimum=1.00 RangeValue.Value=50.00 Value.Value='50'
-++++textbox Name='Test textfield'
+Document Name='Actions'
+++Group IsControlElement=false
+++++Slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=100.00 RangeValue.Minimum=1.00 RangeValue.Value=50.00 Value.Value='50'
+++++Edit Name='Test textfield'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/address-expected-uia-win.txt b/content/test/data/accessibility/html/address-expected-uia-win.txt
index fc3155ce..280eadc 100644
--- a/content/test/data/accessibility/html/address-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/address-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++description Name='Please contact John Citizen for more information.'
+Document
+++Group IsControlElement=false
+++++Text Name='Please contact John Citizen for more information.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/area-expected-uia-win.txt b/content/test/data/accessibility/html/area-expected-uia-win.txt
index 238e9253..f8dee90 100644
--- a/content/test/data/accessibility/html/area-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/area-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++document Name='pipe'
-++++++link Name='pipe1'
-++++++description Name='pipe2'
+Document
+++Group IsControlElement=false
+++++Document Name='pipe'
+++++++Hyperlink Name='pipe1'
+++++++Text Name='pipe2'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/article-expected-uia-win.txt b/content/test/data/accessibility/html/article-expected-uia-win.txt
index 057c893..9117567a 100644
--- a/content/test/data/accessibility/html/article-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/article-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++article ControlType='UIA_GroupControlTypeId' LocalizedControlType='article'
-++++description Name='This is an article element.'
+Document
+++Group LocalizedControlType='article'
+++++Text Name='This is an article element.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/aside-expected-uia-win.txt b/content/test/data/accessibility/html/aside-expected-uia-win.txt
index 6fd86db0..ab252b8f 100644
--- a/content/test/data/accessibility/html/aside-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/aside-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document
-++group IsControlElement=false
-++++description Name='The aside tag defines some content aside from the content it is placed in.'
-++complementary
-++++heading Name='Aside tag'
-++++++description Name='Aside tag' IsControlElement=false
-++++group IsControlElement=false
-++++++description Name='The aside content should be related to the surrounding content.'
+Document
+++Group IsControlElement=false
+++++Text Name='The aside tag defines some content aside from the content it is placed in.'
+++Group
+++++Text Name='Aside tag'
+++++++Text Name='Aside tag' IsControlElement=false
+++++Group IsControlElement=false
+++++++Text Name='The aside content should be related to the surrounding content.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/b-expected-uia-win.txt b/content/test/data/accessibility/html/b-expected-uia-win.txt
index 8f0f41a..d9305a3 100644
--- a/content/test/data/accessibility/html/b-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/b-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='Some '
-++++description Name='bold'
-++++description Name=' text'
+Document
+++Group IsControlElement=false
+++++Text Name='Some '
+++++Text Name='bold'
+++++Text Name=' text'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/bdo-expected-uia-win.txt b/content/test/data/accessibility/html/bdo-expected-uia-win.txt
index 97325d9..fb47567 100644
--- a/content/test/data/accessibility/html/bdo-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/bdo-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++description Name='Some LTR text'
-++++description Name=' '
-++++description Name='Some RTL text '
-++++description Name='with some LTR text embedded'
+Document
+++Group IsControlElement=false
+++++Text Name='Some LTR text'
+++++Text Name=' '
+++++Text Name='Some RTL text '
+++++Text Name='with some LTR text embedded'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/blockquote-expected-uia-win.txt b/content/test/data/accessibility/html/blockquote-expected-uia-win.txt
index b497104..ab30414 100644
--- a/content/test/data/accessibility/html/blockquote-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/blockquote-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group
-++++group IsControlElement=false
-++++++description Name='First blockquote has a child element.'
-++group
-++++description Name='Second blockquote has no child.'
+Document
+++Group
+++++Group IsControlElement=false
+++++++Text Name='First blockquote has a child element.'
+++Group
+++++Text Name='Second blockquote has no child.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/body-expected-uia-win.txt b/content/test/data/accessibility/html/body-expected-uia-win.txt
index d147be46..38cda4f0 100644
--- a/content/test/data/accessibility/html/body-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/body-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++description Name='This test is for body tag'
+Document
+++Group IsControlElement=false
+++++Text Name='This test is for body tag'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/br-expected-uia-win.txt b/content/test/data/accessibility/html/br-expected-uia-win.txt
index 410f106..0c3aeffe 100644
--- a/content/test/data/accessibility/html/br-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/br-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document
-++separator Name='<newline>'
-++description Name='Text line 1'
-++group IsControlElement=false
-++++description Name='Text line 2'
-++++separator Name='<newline>'
-++++description Name='Text line 3'
-++separator Name='<newline>'
+Document
+++Separator Name='<newline>'
+++Text Name='Text line 1'
+++Group IsControlElement=false
+++++Text Name='Text line 2'
+++++Separator Name='<newline>'
+++++Text Name='Text line 3'
+++Separator Name='<newline>'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/button-expected-uia-win.txt b/content/test/data/accessibility/html/button-expected-uia-win.txt
index 49e7ff5..81c50aa 100644
--- a/content/test/data/accessibility/html/button-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/button-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++button Name='Click me!'
+Document
+++Group IsControlElement=false
+++++Button Name='Click me!'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-uia-win.txt b/content/test/data/accessibility/html/button-name-calc-expected-uia-win.txt
index 7a30ee0..3b260f2 100644
--- a/content/test/data/accessibility/html/button-name-calc-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/button-name-calc-expected-uia-win.txt
@@ -1,20 +1,21 @@
-document
-++button Name='InnerText0'
-++button Name='InnerText1' FullDescription='Title1'
-++button Name='AriaLabel2' FullDescription='Title2'
-++button Name='LabelledBy3' FullDescription='Title3'
-++button Name='LabelledBy4' FullDescription='DescribedBy4'
-++button Name='InnerText5' FullDescription='DescribedBy5'
-++button Name='Outer inner'
-++++description Name='Outer' IsControlElement=false
-++++group IsControlElement=false
-++++++description Name='inner' IsControlElement=false
-++button Name='Outer inner1'
-++++description Name='Outer' IsControlElement=false
-++++group Name='inner1'
-++++++description Name='inner2' IsControlElement=false
-++button Name='Outer grandchild'
-++++description Name='Outer' IsControlElement=false
-++++group
-++++++group IsControlElement=false
-++++++++description Name='grandchild' IsControlElement=false
+Document
+++Button Name='InnerText0'
+++Button Name='InnerText1' FullDescription='Title1'
+++Button Name='AriaLabel2' FullDescription='Title2'
+++Button Name='LabelledBy3' FullDescription='Title3'
+++Button Name='LabelledBy4' FullDescription='DescribedBy4'
+++Button Name='InnerText5' FullDescription='DescribedBy5'
+++Button Name='Outer inner'
+++++Text Name='Outer' IsControlElement=false
+++++Group IsControlElement=false
+++++++Text Name='inner' IsControlElement=false
+++Button Name='Outer inner1'
+++++Text Name='Outer' IsControlElement=false
+++++Group Name='inner1'
+++++++Text Name='inner2' IsControlElement=false
+++Button Name='Outer grandchild'
+++++Text Name='Outer' IsControlElement=false
+++++Group
+++++++Group IsControlElement=false
+++++++++Text Name='grandchild' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-uia-win7.txt b/content/test/data/accessibility/html/button-name-calc-expected-uia-win7.txt
index bcff1ef..5b04033 100644
--- a/content/test/data/accessibility/html/button-name-calc-expected-uia-win7.txt
+++ b/content/test/data/accessibility/html/button-name-calc-expected-uia-win7.txt
@@ -1,20 +1,21 @@
-document
-++button Name='InnerText0'
-++button Name='InnerText1'
-++button Name='AriaLabel2'
-++button Name='LabelledBy3'
-++button Name='LabelledBy4'
-++button Name='InnerText5'
-++button Name='Outer inner'
-++++description Name='Outer' IsControlElement=false
-++++group IsControlElement=false
-++++++description Name='inner' IsControlElement=false
-++button Name='Outer inner1'
-++++description Name='Outer' IsControlElement=false
-++++group Name='inner1'
-++++++description Name='inner2' IsControlElement=false
-++button Name='Outer grandchild'
-++++description Name='Outer' IsControlElement=false
-++++group
-++++++group IsControlElement=false
-++++++++description Name='grandchild' IsControlElement=false
\ No newline at end of file
+Document
+++Button Name='InnerText0'
+++Button Name='InnerText1'
+++Button Name='AriaLabel2'
+++Button Name='LabelledBy3'
+++Button Name='LabelledBy4'
+++Button Name='InnerText5'
+++Button Name='Outer inner'
+++++Text Name='Outer' IsControlElement=false
+++++Group IsControlElement=false
+++++++Text Name='inner' IsControlElement=false
+++Button Name='Outer inner1'
+++++Text Name='Outer' IsControlElement=false
+++++Group Name='inner1'
+++++++Text Name='inner2' IsControlElement=false
+++Button Name='Outer grandchild'
+++++Text Name='Outer' IsControlElement=false
+++++Group
+++++++Group IsControlElement=false
+++++++++Text Name='grandchild' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt
index 9f8d2aa9..ff31457 100644
--- a/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt
@@ -1,11 +1,11 @@
-document
-++group IsControlElement=false
-++++group IsControlElement=false
-++++++description Name='Choose one:'
-++++button Name='Choose one: Foo' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='Foo'
-++++listbox Name='Choose one:' Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++option Name='Baz' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
-++++++option Name='Bar' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
-++++++option Name='Foo' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
+Document
+++Group IsControlElement=false
+++++Group IsControlElement=false
+++++++Text Name='Choose one:'
+++++Button Name='Choose one: Foo' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='Foo'
+++++List Name='Choose one:' Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++ListItem Name='Baz' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
+++++++ListItem Name='Bar' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
+++++++ListItem Name='Foo' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
 <-- End-of-file -->
diff --git a/content/test/data/accessibility/html/canvas-expected-uia-win.txt b/content/test/data/accessibility/html/canvas-expected-uia-win.txt
index fcae904..c1c594a 100644
--- a/content/test/data/accessibility/html/canvas-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/canvas-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++group IsControlElement=false
-++++img
-++++++description Name='Static fallback'
-++++img
-++++++link Name='Interactive fallback'
-++++++++description Name='Interactive fallback' IsControlElement=false
+Document
+++Group IsControlElement=false
+++++Image
+++++++Text Name='Static fallback'
+++++Image
+++++++Hyperlink Name='Interactive fallback'
+++++++++Text Name='Interactive fallback' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt b/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt
index dbc3893..6857a09 100644
--- a/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt
@@ -1,21 +1,22 @@
-document
-++group IsControlElement=false
-++++img
-++++++description Name='Static fallback'
-++++img
-++++++description Name='<newline>    '
-++++++group Name='Aria hidden paragraph in fallback content'
-++++++++description Name='Line breaking content in a fallback'
-++++++description Name='<newline>    '
-++++++group Name='Visibility hidden paragraph in fallback content'
-++++++++description Name='This is another paragraph in fallback'
-++++++description Name='<newline>    '
-++++++heading Name='Aria hidden paragraph in fallback content'
-++++++++description Name='Aria hidden paragraph in fallback content' IsControlElement=false
-++++++description Name='<newline>    '
-++++++heading IsControlElement=false
-++++++++description Name='Display none text in fallback content ' IsControlElement=false
-++++++description Name='<newline>    '
-++++++heading IsControlElement=false
-++++++++description Name='Visibility hidden paragraph in fallback content' IsControlElement=false
-++++++description Name='<newline>  '
+Document
+++Group IsControlElement=false
+++++Image
+++++++Text Name='Static fallback'
+++++Image
+++++++Text Name='<newline>    '
+++++++Group Name='Aria hidden paragraph in fallback content'
+++++++++Text Name='Line breaking content in a fallback'
+++++++Text Name='<newline>    '
+++++++Group Name='Visibility hidden paragraph in fallback content'
+++++++++Text Name='This is another paragraph in fallback'
+++++++Text Name='<newline>    '
+++++++Text Name='Aria hidden paragraph in fallback content'
+++++++++Text Name='Aria hidden paragraph in fallback content' IsControlElement=false
+++++++Text Name='<newline>    '
+++++++Text IsControlElement=false
+++++++++Text Name='Display none text in fallback content ' IsControlElement=false
+++++++Text Name='<newline>    '
+++++++Text IsControlElement=false
+++++++++Text Name='Visibility hidden paragraph in fallback content' IsControlElement=false
+++++++Text Name='<newline>  '
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/caption-expected-uia-win.txt b/content/test/data/accessibility/html/caption-expected-uia-win.txt
index c72e2c7..ba5fe04 100644
--- a/content/test/data/accessibility/html/caption-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/caption-expected-uia-win.txt
@@ -1,19 +1,20 @@
-document
-++grid Name='Browser and Engine' Grid.ColumnCount=2 Grid.RowCount=3 Table.RowOrColumnMajor='RowMajor'
-++++description IsControlElement=false
-++++++description Name='Browser and Engine'
-++++row IsControlElement=false
-++++++columnheader Name='Browser' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
-++++++++description Name='Browser' IsControlElement=false
-++++++columnheader Name='Engine' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
-++++++++description Name='Engine' IsControlElement=false
-++++row IsControlElement=false
-++++++gridcell Name='Chrome' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
-++++++++description Name='Chrome' IsControlElement=false
-++++++gridcell Name='Blink' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
-++++++++description Name='Blink' IsControlElement=false
-++++row IsControlElement=false
-++++++gridcell Name='Safari' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
-++++++++description Name='Safari' IsControlElement=false
-++++++gridcell Name='WebKit' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
-++++++++description Name='WebKit' IsControlElement=false
+Document
+++Table Name='Browser and Engine' Grid.ColumnCount=2 Grid.RowCount=3 Table.RowOrColumnMajor='RowMajor'
+++++Text IsControlElement=false
+++++++Text Name='Browser and Engine'
+++++DataItem IsControlElement=false
+++++++DataItem Name='Browser' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
+++++++++Text Name='Browser' IsControlElement=false
+++++++DataItem Name='Engine' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
+++++++++Text Name='Engine' IsControlElement=false
+++++DataItem IsControlElement=false
+++++++DataItem Name='Chrome' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
+++++++++Text Name='Chrome' IsControlElement=false
+++++++DataItem Name='Blink' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
+++++++++Text Name='Blink' IsControlElement=false
+++++DataItem IsControlElement=false
+++++++DataItem Name='Safari' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
+++++++++Text Name='Safari' IsControlElement=false
+++++++DataItem Name='WebKit' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1 GridItem.ContainingGrid='Browser and Engine'
+++++++++Text Name='WebKit' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/checkbox-name-calc-expected-uia-win.txt b/content/test/data/accessibility/html/checkbox-name-calc-expected-uia-win.txt
index f097f3db..01cccc0 100644
--- a/content/test/data/accessibility/html/checkbox-name-calc-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/checkbox-name-calc-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++checkbox Name='Title0' Toggle.ToggleState='Off'
-++checkbox Name='Label1' Toggle.ToggleState='Off'
-++checkbox Name='AriaLabel2' Toggle.ToggleState='Off'
-++checkbox Name='LabelledBy3' Toggle.ToggleState='Off'
-++checkbox Name='LabelledBy4' Toggle.ToggleState='Off'
-++checkbox Toggle.ToggleState='Off'
+Document
+++CheckBox Name='Title0' Toggle.ToggleState='Off'
+++CheckBox Name='Label1' Toggle.ToggleState='Off'
+++CheckBox Name='AriaLabel2' Toggle.ToggleState='Off'
+++CheckBox Name='LabelledBy3' Toggle.ToggleState='Off'
+++CheckBox Name='LabelledBy4' Toggle.ToggleState='Off'
+++CheckBox Toggle.ToggleState='Off'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/cite-expected-uia-win.txt b/content/test/data/accessibility/html/cite-expected-uia-win.txt
index 9d22eb8..168a646 100644
--- a/content/test/data/accessibility/html/cite-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/cite-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++img Name='Pipe'
-++group IsControlElement=false
-++++description Name='The pipe'
-++++description Name=' clicked by SomeOne.'
+Document
+++Image Name='Pipe'
+++Group IsControlElement=false
+++++Text Name='The pipe'
+++++Text Name=' clicked by SomeOne.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/combobox-optgroup-expected-uia-win.txt b/content/test/data/accessibility/html/combobox-optgroup-expected-uia-win.txt
index 8d7027d..63a71be 100644
--- a/content/test/data/accessibility/html/combobox-optgroup-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/combobox-optgroup-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document
-++group IsControlElement=false
-++++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.IsReadOnly=false Value.Value='Mercedes Label'
-++++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false Value.IsReadOnly=false
-++++++++listitem Name='Volvo Label' SelectionItem.IsSelected=false
-++++++++listitem Name='Saab Label' SelectionItem.IsSelected=false
-++++++++listitem Name='Mercedes Label' SelectionItem.IsSelected=true
-++++++++listitem Name='Audi Label' SelectionItem.IsSelected=false
+Document
+++Group IsControlElement=false
+++++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.IsReadOnly=false Value.Value='Mercedes Label'
+++++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false Value.IsReadOnly=false
+++++++++ListItem Name='Volvo Label' SelectionItem.IsSelected=false
+++++++++ListItem Name='Saab Label' SelectionItem.IsSelected=false
+++++++++ListItem Name='Mercedes Label' SelectionItem.IsSelected=true
+++++++++ListItem Name='Audi Label' SelectionItem.IsSelected=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-uia-win.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-uia-win.txt
index 0fd4e7f..108f5bc 100644
--- a/content/test/data/accessibility/html/contenteditable-descendants-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-uia-win.txt
@@ -1,23 +1,24 @@
-document
-++group
-++++group IsControlElement=false
-++++++description Name='A contenteditable with a '
-++++++link Name='link'
-++++++++description Name='link' IsControlElement=false
-++++++description Name=' and an '
-++++++img Name='Image'
-++++++description Name=' and a '
-++++++button Name='Button'
-++++++description Name='.'
-++++grid Grid.ColumnCount=1 Grid.RowCount=1
-++++++row IsControlElement=false
-++++++++gridcell Name='Always expose editable tables as tables.' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++++description Name='Always expose editable tables as tables.' IsControlElement=false
-++++list
-++++++listitem
-++++++++description Name='1. '
-++++++++description Name='Editable list item.' IsControlElement=false
-++group IsControlElement=false
-++++description Name='Non-editable paragraph.'
-++group
-++++description Name='Should keep the role but change the state.'
+Document
+++Group
+++++Group IsControlElement=false
+++++++Text Name='A contenteditable with a '
+++++++Hyperlink Name='link'
+++++++++Text Name='link' IsControlElement=false
+++++++Text Name=' and an '
+++++++Image Name='Image'
+++++++Text Name=' and a '
+++++++Button Name='Button'
+++++++Text Name='.'
+++++Table Grid.ColumnCount=1 Grid.RowCount=1
+++++++DataItem IsControlElement=false
+++++++++DataItem Name='Always expose editable tables as tables.' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++++Text Name='Always expose editable tables as tables.' IsControlElement=false
+++++List
+++++++ListItem
+++++++++Text Name='1. '
+++++++++Text Name='Editable list item.' IsControlElement=false
+++Group IsControlElement=false
+++++Text Name='Non-editable paragraph.'
+++Group
+++++Text Name='Should keep the role but change the state.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-uia-win.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-uia-win.txt
index ca2839b..25e26fc 100644
--- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-uia-win.txt
@@ -1,19 +1,20 @@
-document
-++group
-++++group IsControlElement=false
-++++++description Name='A contenteditable with a '
-++++++link Name='link'
-++++++++description Name='link' IsControlElement=false
-++++++description Name=' and an '
-++++++img Name='Image'
-++++++description Name=' and a '
-++++++button Name='Button'
-++++++description Name='.'
-++++grid Grid.ColumnCount=1 Grid.RowCount=1
-++++++row IsControlElement=false
-++++++++gridcell Name='Always expose editable tables as tables.' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++++description Name='Always expose editable tables as tables.' IsControlElement=false
-++++list
-++++++listitem
-++++++++description Name='1. '
-++++++++description Name='Editable list item.' IsControlElement=false
+Document
+++Group
+++++Group IsControlElement=false
+++++++Text Name='A contenteditable with a '
+++++++Hyperlink Name='link'
+++++++++Text Name='link' IsControlElement=false
+++++++Text Name=' and an '
+++++++Image Name='Image'
+++++++Text Name=' and a '
+++++++Button Name='Button'
+++++++Text Name='.'
+++++Table Grid.ColumnCount=1 Grid.RowCount=1
+++++++DataItem IsControlElement=false
+++++++++DataItem Name='Always expose editable tables as tables.' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++++Text Name='Always expose editable tables as tables.' IsControlElement=false
+++++List
+++++++ListItem
+++++++++Text Name='1. '
+++++++++Text Name='Editable list item.' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-uia-win.txt b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-uia-win.txt
index 87987f4..b53b59de7 100644
--- a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-uia-win.txt
@@ -1,10 +1,11 @@
-document
-++group
-++++group IsControlElement=false
-++++++description Name='This is editable.'
-++++description Name='This is not editable.'
-++++separator Name='<newline>'
-++++group
-++++++description Name='But this one is.'
-++++group
-++++++description Name='So is this one.'
+Document
+++Group
+++++Group IsControlElement=false
+++++++Text Name='This is editable.'
+++++Text Name='This is not editable.'
+++++Separator Name='<newline>'
+++++Group
+++++++Text Name='But this one is.'
+++++Group
+++++++Text Name='So is this one.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-uia-win.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-uia-win.txt
index 70096a0..7180b0d5 100644
--- a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group Name='label'
-++group
-++group Name='title'
-++group IsControlElement=false
-++++description Name='description'
+Document
+++Group Name='label'
+++Group
+++Group Name='title'
+++Group IsControlElement=false
+++++Text Name='description'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/dd-expected-uia-win.txt b/content/test/data/accessibility/html/dd-expected-uia-win.txt
index 353dd1c..959d844 100644
--- a/content/test/data/accessibility/html/dd-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/dd-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++list
-++++listitem IsControlElement=false
-++++++description Name='Coffee'
-++++description IsControlElement=false
-++++++description Name='Black hot drink'
+Document
+++List
+++++ListItem IsControlElement=false
+++++++Text Name='Coffee'
+++++Text IsControlElement=false
+++++++Text Name='Black hot drink'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/del-expected-uia-win.txt b/content/test/data/accessibility/html/del-expected-uia-win.txt
index ba63f04..1e8c418 100644
--- a/content/test/data/accessibility/html/del-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/del-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='I am '
-++++group IsControlElement=false
-++++++description Name='vegetarian'
+Document
+++Group IsControlElement=false
+++++Text Name='I am '
+++++Group IsControlElement=false
+++++++Text Name='vegetarian'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/details-expected-uia-win.txt b/content/test/data/accessibility/html/details-expected-uia-win.txt
index 21955a7..372b8f7 100644
--- a/content/test/data/accessibility/html/details-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/details-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document
-++group LocalizedControlType='details'
-++++button Name='details tag' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++++description Name='details tag'
-++group LocalizedControlType='details'
-++++button Name='details tag open' ExpandCollapse.ExpandCollapseState='Expanded'
-++++++description Name='details tag open'
-++++group IsControlElement=false
-++++++description Name='The details tag with open specifies that the details should be visible (open) to the user.'
+Document
+++Group LocalizedControlType='details'
+++++Button Name='details tag' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++++Text Name='details tag'
+++Group LocalizedControlType='details'
+++++Button Name='details tag open' ExpandCollapse.ExpandCollapseState='Expanded'
+++++++Text Name='details tag open'
+++++Group IsControlElement=false
+++++++Text Name='The details tag with open specifies that the details should be visible (open) to the user.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/dfn-expected-uia-win.txt b/content/test/data/accessibility/html/dfn-expected-uia-win.txt
index 839efe8..c75ba543 100644
--- a/content/test/data/accessibility/html/dfn-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/dfn-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++description Name='Web Browser'
-++++description Name=' A computer program with a graphical user interface for displaying HTML files, used to navigate the World Wide Web.'
+Document
+++Group IsControlElement=false
+++++Text Name='Web Browser'
+++++Text Name=' A computer program with a graphical user interface for displaying HTML files, used to navigate the World Wide Web.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/dialog-expected-uia-win.txt b/content/test/data/accessibility/html/dialog-expected-uia-win.txt
index aed70ec..37ad3409 100644
--- a/content/test/data/accessibility/html/dialog-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/dialog-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++dialog IsControlElement=false Window.IsModal=false
-++++description Name='Text in dialog'
+Document
+++Pane IsControlElement=false Window.IsModal=false
+++++Text Name='Text in dialog'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/div-expected-uia-win.txt b/content/test/data/accessibility/html/div-expected-uia-win.txt
index f9062bd5..d963f2d5 100644
--- a/content/test/data/accessibility/html/div-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/div-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='Unfocusable div'
-++group Name='Focusable div'
-++++description Name='Focusable div'
+Document
+++Group IsControlElement=false
+++++Text Name='Unfocusable div'
+++Group Name='Focusable div'
+++++Text Name='Focusable div'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/dl-expected-uia-win.txt b/content/test/data/accessibility/html/dl-expected-uia-win.txt
index efd067b..0b9cc322 100644
--- a/content/test/data/accessibility/html/dl-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/dl-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document
-++list
-++++listitem IsControlElement=false
-++++++description Name='Term'
-++++description IsControlElement=false
-++++++description Name='Description'
-++definition
-++++description Name='Definition'
+Document
+++List
+++++ListItem IsControlElement=false
+++++++Text Name='Term'
+++++Text IsControlElement=false
+++++++Text Name='Description'
+++Group
+++++Text Name='Definition'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/dt-expected-uia-win.txt b/content/test/data/accessibility/html/dt-expected-uia-win.txt
index 353dd1c..959d844 100644
--- a/content/test/data/accessibility/html/dt-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/dt-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++list
-++++listitem IsControlElement=false
-++++++description Name='Coffee'
-++++description IsControlElement=false
-++++++description Name='Black hot drink'
+Document
+++List
+++++ListItem IsControlElement=false
+++++++Text Name='Coffee'
+++++Text IsControlElement=false
+++++++Text Name='Black hot drink'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/element-class-id-src-attr-expected-uia-win.txt b/content/test/data/accessibility/html/element-class-id-src-attr-expected-uia-win.txt
index cba9026..328a261 100644
--- a/content/test/data/accessibility/html/element-class-id-src-attr-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/element-class-id-src-attr-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++heading Name='Image'
-++++description Name='Image' IsControlElement=false
-++img Name='ImageAlt'
+Document
+++Text Name='Image'
+++++Text Name='Image' IsControlElement=false
+++Image Name='ImageAlt'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/em-expected-uia-win.txt b/content/test/data/accessibility/html/em-expected-uia-win.txt
index b1f752c..5ea0eae1 100644
--- a/content/test/data/accessibility/html/em-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/em-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='One word is '
-++++description Name='emphasized'
-++++description Name='.'
+Document
+++Group IsControlElement=false
+++++Text Name='One word is '
+++++Text Name='emphasized'
+++++Text Name='.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/embed-expected-uia-win.txt b/content/test/data/accessibility/html/embed-expected-uia-win.txt
index 8cf75072..56da86f 100644
--- a/content/test/data/accessibility/html/embed-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/embed-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++document
+Document
+++Group IsControlElement=false
+++++Pane
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/fieldset-expected-uia-win.txt b/content/test/data/accessibility/html/fieldset-expected-uia-win.txt
index 85832c9..83b9965 100644
--- a/content/test/data/accessibility/html/fieldset-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/fieldset-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++form IsControlElement=false
-++++group Name='Browser Engines:'
-++++++description IsControlElement=false
-++++++++description Name='Browser Engines:' IsControlElement=false
+Document
+++Group IsControlElement=false
+++++Group Name='Browser Engines:'
+++++++Text IsControlElement=false
+++++++++Text Name='Browser Engines:' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/figcaption-expected-uia-win.txt b/content/test/data/accessibility/html/figcaption-expected-uia-win.txt
index 86d7818..8409d1af 100644
--- a/content/test/data/accessibility/html/figcaption-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/figcaption-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group Name='Fig.1 - A green Box'
-++++img Name='This is a green box.'
-++++description ControlType='UIA_TextControlTypeId' IsControlElement=false
-++++++description ControlType='UIA_TextControlTypeId' Name='Fig.1 - A green Box'
+Document
+++Group Name='Fig.1 - A green Box'
+++++Image Name='This is a green box.'
+++++Text IsControlElement=false
+++++++Text Name='Fig.1 - A green Box'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/figure-expected-uia-win.txt b/content/test/data/accessibility/html/figure-expected-uia-win.txt
index 1eb4524..80d5f36 100644
--- a/content/test/data/accessibility/html/figure-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/figure-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group LocalizedControlType='figure'
-++++img Name='Sunspots'
+Document
+++Group LocalizedControlType='figure'
+++++Image Name='Sunspots'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/footer-expected-uia-win.txt b/content/test/data/accessibility/html/footer-expected-uia-win.txt
index 744fa61..5d5fff4 100644
--- a/content/test/data/accessibility/html/footer-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/footer-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++contentinfo LocalizedControlType='footer' LocalizedLandmarkType='content information'
-++++description Name='Footer element'
+Document
+++Group LocalizedControlType='footer' LocalizedLandmarkType='content information'
+++++Text Name='Footer element'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/footer-expected-uia-win7.txt b/content/test/data/accessibility/html/footer-expected-uia-win7.txt
index 8817c8c..a0433b5 100644
--- a/content/test/data/accessibility/html/footer-expected-uia-win7.txt
+++ b/content/test/data/accessibility/html/footer-expected-uia-win7.txt
@@ -1,3 +1,4 @@
-document
-++contentinfo LocalizedControlType='footer'
-++++description Name='Footer element'
+Document
+++Group LocalizedControlType='footer'
+++++Text Name='Footer element'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/footer-inside-other-section-expected-uia-win.txt b/content/test/data/accessibility/html/footer-inside-other-section-expected-uia-win.txt
index 671568a..1ef9e077 100644
--- a/content/test/data/accessibility/html/footer-inside-other-section-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/footer-inside-other-section-expected-uia-win.txt
@@ -1,13 +1,14 @@
-document
-++article
-++++group LocalizedControlType='footer'
-++++++group IsControlElement=false
-++++++++description Name='footer inside article.'
-++group
-++++group LocalizedControlType='footer'
-++++++group IsControlElement=false
-++++++++description Name='footer inside section.'
-++main
-++++group LocalizedControlType='footer'
-++++++group IsControlElement=false
-++++++++description Name='footer inside main.'
+Document
+++Group
+++++Group LocalizedControlType='footer'
+++++++Group IsControlElement=false
+++++++++Text Name='footer inside article.'
+++Group
+++++Group LocalizedControlType='footer'
+++++++Group IsControlElement=false
+++++++++Text Name='footer inside section.'
+++Group
+++++Group LocalizedControlType='footer'
+++++++Group IsControlElement=false
+++++++++Text Name='footer inside main.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/form-expected-uia-win.txt b/content/test/data/accessibility/html/form-expected-uia-win.txt
index a5be5f1..7801cb85 100644
--- a/content/test/data/accessibility/html/form-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/form-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++form IsControlElement=false
-++++button Name='Submit'
+Document
+++Group IsControlElement=false
+++++Button Name='Submit'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/form-validation-message-expected-uia-win.txt b/content/test/data/accessibility/html/form-validation-message-expected-uia-win.txt
index 41cf4b2..fb5d2d21 100644
--- a/content/test/data/accessibility/html/form-validation-message-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/form-validation-message-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++form IsControlElement=false
-++++description
-++++++description Name='Pet name:'
-++++textbox Name='Pet name:' IsRequiredForForm=true
-++alert Name='Please enter pet name'
+Document
+++Group IsControlElement=false
+++++Text
+++++++Text Name='Pet name:'
+++++Edit Name='Pet name:' IsRequiredForForm=true
+++Text Name='Please enter pet name'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/frameset-expected-uia-win.txt b/content/test/data/accessibility/html/frameset-expected-uia-win.txt
index 5f332dc..32ef044 100644
--- a/content/test/data/accessibility/html/frameset-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/frameset-expected-uia-win.txt
@@ -1,18 +1,19 @@
-document
-++document
-++++document
-++++++group IsControlElement=false
-++++++++description Name='My favorite browser is '
-++++++++group IsControlElement=false
-++++++++++description Name='ABC'
-++++++++description Name=' '
-++++++++group IsControlElement=false
-++++++++++description Name='Chrome'
-++++++++description Name='!'
-++document
-++++document
-++++++group IsControlElement=false
-++++++++description Name='This test is to check '
-++++++++description IsControlElement=false
-++++++++++description Name='mark tag'
-++++++++description Name='.'
+Document
+++Document
+++++Document
+++++++Group IsControlElement=false
+++++++++Text Name='My favorite browser is '
+++++++++Group IsControlElement=false
+++++++++++Text Name='ABC'
+++++++++Text Name=' '
+++++++++Group IsControlElement=false
+++++++++++Text Name='Chrome'
+++++++++Text Name='!'
+++Document
+++++Document
+++++++Group IsControlElement=false
+++++++++Text Name='This test is to check '
+++++++++Text IsControlElement=false
+++++++++++Text Name='mark tag'
+++++++++Text Name='.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/header-expected-uia-win.txt b/content/test/data/accessibility/html/header-expected-uia-win.txt
index 4ae30012..4ac24c2 100644
--- a/content/test/data/accessibility/html/header-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/header-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++banner LocalizedControlType='header'
-++++description Name='Chromium Browser'
+Document
+++Group LocalizedControlType='header'
+++++Text Name='Chromium Browser'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/header-inside-other-section-expected-uia-win.txt b/content/test/data/accessibility/html/header-inside-other-section-expected-uia-win.txt
index 0f92375..9194254 100644
--- a/content/test/data/accessibility/html/header-inside-other-section-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/header-inside-other-section-expected-uia-win.txt
@@ -1,13 +1,14 @@
-document
-++article
-++++group LocalizedControlType='header'
-++++++group IsControlElement=false
-++++++++description Name='Header inside article.'
-++group
-++++group LocalizedControlType='header'
-++++++group IsControlElement=false
-++++++++description Name='Header inside section.'
-++main
-++++group LocalizedControlType='header'
-++++++group IsControlElement=false
-++++++++description Name='Header inside main.'
+Document
+++Group
+++++Group LocalizedControlType='header'
+++++++Group IsControlElement=false
+++++++++Text Name='Header inside article.'
+++Group
+++++Group LocalizedControlType='header'
+++++++Group IsControlElement=false
+++++++++Text Name='Header inside section.'
+++Group
+++++Group LocalizedControlType='header'
+++++++Group IsControlElement=false
+++++++++Text Name='Header inside main.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/heading-expected-uia-win.txt b/content/test/data/accessibility/html/heading-expected-uia-win.txt
index d46397809..c1da12e0 100644
--- a/content/test/data/accessibility/html/heading-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/heading-expected-uia-win.txt
@@ -1,13 +1,14 @@
-document
-++heading Name='Heading 1'
-++++description Name='Heading 1' IsControlElement=false
-++heading Name='Heading 2'
-++++description Name='Heading 2' IsControlElement=false
-++heading Name='Heading 3'
-++++description Name='Heading 3' IsControlElement=false
-++heading Name='Heading 4'
-++++description Name='Heading 4' IsControlElement=false
-++heading Name='Heading 5'
-++++description Name='Heading 5' IsControlElement=false
-++heading Name='Heading 6'
-++++description Name='Heading 6' IsControlElement=false
+Document
+++Text Name='Heading 1'
+++++Text Name='Heading 1' IsControlElement=false
+++Text Name='Heading 2'
+++++Text Name='Heading 2' IsControlElement=false
+++Text Name='Heading 3'
+++++Text Name='Heading 3' IsControlElement=false
+++Text Name='Heading 4'
+++++Text Name='Heading 4' IsControlElement=false
+++Text Name='Heading 5'
+++++Text Name='Heading 5' IsControlElement=false
+++Text Name='Heading 6'
+++++Text Name='Heading 6' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/hr-expected-uia-win.txt b/content/test/data/accessibility/html/hr-expected-uia-win.txt
index dcb50d2d..6ecff90d 100644
--- a/content/test/data/accessibility/html/hr-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/hr-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document
-++group IsControlElement=false
-++++description Name='Before.'
-++separator Name='Dividing line'
-++group IsControlElement=false
-++++description Name='Middle.'
-++separator
-++group IsControlElement=false
-++++description Name='After.'
+Document
+++Group IsControlElement=false
+++++Text Name='Before.'
+++Separator Name='Dividing line'
+++Group IsControlElement=false
+++++Text Name='Middle.'
+++Separator
+++Group IsControlElement=false
+++++Text Name='After.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/i-expected-uia-win.txt b/content/test/data/accessibility/html/i-expected-uia-win.txt
index 654576b..d67794e 100644
--- a/content/test/data/accessibility/html/i-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/i-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='This is to check '
-++++description Name='italic property'
-++++description Name=' using i tag.'
+Document
+++Group IsControlElement=false
+++++Text Name='This is to check '
+++++Text Name='italic property'
+++++Text Name=' using i tag.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/iframe-coordinates-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-coordinates-expected-uia-win.txt
index e66ec72..fbdec8ed 100644
--- a/content/test/data/accessibility/html/iframe-coordinates-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/iframe-coordinates-expected-uia-win.txt
@@ -1,15 +1,16 @@
-document
-++group IsControlElement=false
-++++button Name='Button'
-++group IsControlElement=false
-++++button Name='Button'
-++group IsControlElement=false
-++++document
-++++++document
-++++++++group IsControlElement=false
-++++++++++button Name='Ordinary Button'
-++group IsControlElement=false
-++++document
-++++++document
-++++++++group IsControlElement=false
-++++++++++button Name='Scrolled Button'
+Document
+++Group IsControlElement=false
+++++Button Name='Button'
+++Group IsControlElement=false
+++++Button Name='Button'
+++Group IsControlElement=false
+++++Document
+++++++Document
+++++++++Group IsControlElement=false
+++++++++++Button Name='Ordinary Button'
+++Group IsControlElement=false
+++++Document
+++++++Document
+++++++++Group IsControlElement=false
+++++++++++Button Name='Scrolled Button'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/iframe-cross-process-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-cross-process-expected-uia-win.txt
index d76a066..66d83c5 100644
--- a/content/test/data/accessibility/html/iframe-cross-process-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/iframe-cross-process-expected-uia-win.txt
@@ -1,10 +1,11 @@
-document
-++group IsControlElement=false
-++++description Name='Before frame'
-++group IsControlElement=false
-++++document Name='Cross-process iframe'
-++++++document
-++++++++group IsControlElement=false
-++++++++++description Name='Text in iframe'
-++group IsControlElement=false
-++++description Name='After frame'
+Document
+++Group IsControlElement=false
+++++Text Name='Before frame'
+++Group IsControlElement=false
+++++Document Name='Cross-process iframe'
+++++++Document
+++++++++Group IsControlElement=false
+++++++++++Text Name='Text in iframe'
+++Group IsControlElement=false
+++++Text Name='After frame'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/iframe-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-expected-uia-win.txt
index 4b8e7471..a2b9659 100644
--- a/content/test/data/accessibility/html/iframe-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/iframe-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++document Name='Empty iframe'
-++++++document
+Document
+++Group IsControlElement=false
+++++Document Name='Empty iframe'
+++++++Document
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/iframe-presentational-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-presentational-expected-uia-win.txt
index 6638dc1d..6183ef9 100644
--- a/content/test/data/accessibility/html/iframe-presentational-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/iframe-presentational-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++group
-++++++group
+Document
+++Group IsControlElement=false
+++++Group
+++++++Group
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt
index 8290e16a..e3fd32c 100644
--- a/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++document
-++++document
-++++++img
-++document
-++++document
-++++++img
+Document
+++Document
+++++Document
+++++++Image
+++Document
+++++Document
+++++++Image
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ignored-selection-between-text-expected-uia-win.txt b/content/test/data/accessibility/html/ignored-selection-between-text-expected-uia-win.txt
index 45e007c..a07b593 100644
--- a/content/test/data/accessibility/html/ignored-selection-between-text-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ignored-selection-between-text-expected-uia-win.txt
@@ -1,8 +1,9 @@
-document
-++group IsControlElement=false
-++++description Name='before selection'
-++group IsControlElement=false
-++++description Name='this text is not ignored'
-++group IsControlElement=false
-++++description Name='after selection'
-++description Name='Done'
+Document
+++Group IsControlElement=false
+++++Text Name='before selection'
+++Group IsControlElement=false
+++++Text Name='this text is not ignored'
+++Group IsControlElement=false
+++++Text Name='after selection'
+++Text Name='Done'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ignored-selection-expected-uia-win.txt b/content/test/data/accessibility/html/ignored-selection-expected-uia-win.txt
index 12c051eb..82c12758 100644
--- a/content/test/data/accessibility/html/ignored-selection-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ignored-selection-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++description Name='this text is not ignored'
-++group IsControlElement=false
-++++description Name='after selection'
-++description Name='Done'
+Document
+++Text Name='this text is not ignored'
+++Group IsControlElement=false
+++++Text Name='after selection'
+++Text Name='Done'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ignored-selection-no-unignored-expected-uia-win.txt b/content/test/data/accessibility/html/ignored-selection-no-unignored-expected-uia-win.txt
index a322991..a44b16b4 100644
--- a/content/test/data/accessibility/html/ignored-selection-no-unignored-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ignored-selection-no-unignored-expected-uia-win.txt
@@ -1,2 +1,3 @@
-document
-++description Name='Done'
+Document
+++Text Name='Done'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/img-empty-alt-expected-uia-win.txt b/content/test/data/accessibility/html/img-empty-alt-expected-uia-win.txt
index e386a0f5..e52f496 100644
--- a/content/test/data/accessibility/html/img-empty-alt-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/img-empty-alt-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++img IsControlElement=false
-++++img
-++++img Name='full'
+Document
+++Group IsControlElement=false
+++++Image IsControlElement=false
+++++Image
+++++Image Name='full'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/img-expected-uia-win.txt b/content/test/data/accessibility/html/img-expected-uia-win.txt
index ca96c95a..09b1da33 100644
--- a/content/test/data/accessibility/html/img-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/img-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++img Name='pipe'
-++++description Name=' '
-++++description Name=' '
-++++img Name='  '
+Document
+++Group IsControlElement=false
+++++Image Name='pipe'
+++++Text Name=' '
+++++Text Name=' '
+++++Image Name='  '
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/img-link-empty-alt-expected-uia-win.txt b/content/test/data/accessibility/html/img-link-empty-alt-expected-uia-win.txt
index 38f51658..b3a85da 100644
--- a/content/test/data/accessibility/html/img-link-empty-alt-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/img-link-empty-alt-expected-uia-win.txt
@@ -1,11 +1,12 @@
-document
-++group IsControlElement=false
-++++link Name='unread '
-++++++description Name='unread ' IsControlElement=false
-++++link Name='read '
-++++++description Name='read ' IsControlElement=false
-++++link Name='read '
-++++++description Name='read ' IsControlElement=false
-++++link Name='read'
-++++++img
-++++++description Name='read' IsControlElement=false
+Document
+++Group IsControlElement=false
+++++Hyperlink Name='unread '
+++++++Text Name='unread ' IsControlElement=false
+++++Hyperlink Name='read '
+++++++Text Name='read ' IsControlElement=false
+++++Hyperlink Name='read '
+++++++Text Name='read ' IsControlElement=false
+++++Hyperlink Name='read'
+++++++Image
+++++++Text Name='read' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/in-page-links-expected-uia-win.txt b/content/test/data/accessibility/html/in-page-links-expected-uia-win.txt
index 96a64087..6a82693 100644
--- a/content/test/data/accessibility/html/in-page-links-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/in-page-links-expected-uia-win.txt
@@ -1,35 +1,36 @@
-document
-++link Name='Empty anchor'
-++++description Name='Empty anchor' IsControlElement=false
-++description Name=' '
-++link Name='Anchor with content'
-++++description Name='Anchor with content' IsControlElement=false
-++description Name=' '
-++link Name='Anchor with ID'
-++++description Name='Anchor with ID' IsControlElement=false
-++description Name=' '
-++link Name='Empty span'
-++++description Name='Empty span' IsControlElement=false
-++description Name=' '
-++link Name='Span with content'
-++++description Name='Span with content' IsControlElement=false
-++description Name=' '
-++link Name='Paragraph with content'
-++++description Name='Paragraph with content' IsControlElement=false
-++group IsControlElement=false
-++++link
-++++description Name='After empty anchor'
-++group IsControlElement=false
-++++link Name='Anchor with content'
-++++++description Name='Anchor with content'
-++group IsControlElement=false
-++++link Name='Anchor with ID'
-++++++description Name='Anchor with ID'
-++group IsControlElement=false
-++++group IsControlElement=false
-++++description Name='After empty span'
-++group IsControlElement=false
-++++group IsControlElement=false
-++++++description Name='Span with content'
-++group IsControlElement=false
-++++description Name='Paragraph with content'
+Document
+++Hyperlink Name='Empty anchor'
+++++Text Name='Empty anchor' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Anchor with content'
+++++Text Name='Anchor with content' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Anchor with ID'
+++++Text Name='Anchor with ID' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Empty span'
+++++Text Name='Empty span' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Span with content'
+++++Text Name='Span with content' IsControlElement=false
+++Text Name=' '
+++Hyperlink Name='Paragraph with content'
+++++Text Name='Paragraph with content' IsControlElement=false
+++Group IsControlElement=false
+++++Hyperlink
+++++Text Name='After empty anchor'
+++Group IsControlElement=false
+++++Hyperlink Name='Anchor with content'
+++++++Text Name='Anchor with content'
+++Group IsControlElement=false
+++++Hyperlink Name='Anchor with ID'
+++++++Text Name='Anchor with ID'
+++Group IsControlElement=false
+++++Group IsControlElement=false
+++++Text Name='After empty span'
+++Group IsControlElement=false
+++++Group IsControlElement=false
+++++++Text Name='Span with content'
+++Group IsControlElement=false
+++++Text Name='Paragraph with content'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-button-expected-uia-win.txt b/content/test/data/accessibility/html/input-button-expected-uia-win.txt
index 07fa9a6..fe57d81 100644
--- a/content/test/data/accessibility/html/input-button-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-button-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++button Name='Button'
+Document
+++Group IsControlElement=false
+++++Button Name='Button'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-button-in-menu-expected-uia-win.txt b/content/test/data/accessibility/html/input-button-in-menu-expected-uia-win.txt
index 98daa9fc..6833aafd 100644
--- a/content/test/data/accessibility/html/input-button-in-menu-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-button-in-menu-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++menuitem Name='Button in menu element'
-++menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++menuitem Name='Button in element with menu role'
+Document
+++Group IsControlElement=false
+++++MenuItem Name='Button in menu element'
+++Menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++MenuItem Name='Button in element with menu role'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-checkbox-expected-uia-win.txt b/content/test/data/accessibility/html/input-checkbox-expected-uia-win.txt
index 86a631c..6cdfded 100644
--- a/content/test/data/accessibility/html/input-checkbox-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-checkbox-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++group IsControlElement=false
-++++checkbox Name='Checkbox0' Toggle.ToggleState='Off'
-++++checkbox Name='Checkbox1' Toggle.ToggleState='On'
-++++checkbox Name='Checkbox2' Toggle.ToggleState='On'
-++++checkbox Name='Checkbox3' Toggle.ToggleState='On'
-++++checkbox Name='Checkbox4' Toggle.ToggleState='Indeterminate'
+Document
+++Group IsControlElement=false
+++++CheckBox Name='Checkbox0' Toggle.ToggleState='Off'
+++++CheckBox Name='Checkbox1' Toggle.ToggleState='On'
+++++CheckBox Name='Checkbox2' Toggle.ToggleState='On'
+++++CheckBox Name='Checkbox3' Toggle.ToggleState='On'
+++++CheckBox Name='Checkbox4' Toggle.ToggleState='Indeterminate'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-checkbox-in-menu-expected-uia-win.txt b/content/test/data/accessibility/html/input-checkbox-in-menu-expected-uia-win.txt
index 060c6ea..0ebde5e 100644
--- a/content/test/data/accessibility/html/input-checkbox-in-menu-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-checkbox-in-menu-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++group IsControlElement=false
-++++checkbox Name='Checkbox1' Toggle.ToggleState='Off'
-++++checkbox Name='Checkbox2' Toggle.ToggleState='On'
-++menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++checkbox Name='Checkbox3' Toggle.ToggleState='On'
-++++checkbox Name='Checkbox4' Toggle.ToggleState='Indeterminate'
+Document
+++Group IsControlElement=false
+++++CheckBox Name='Checkbox1' Toggle.ToggleState='Off'
+++++CheckBox Name='Checkbox2' Toggle.ToggleState='On'
+++Menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++CheckBox Name='Checkbox3' Toggle.ToggleState='On'
+++++CheckBox Name='Checkbox4' Toggle.ToggleState='Indeterminate'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-color-expected-uia-win.txt b/content/test/data/accessibility/html/input-color-expected-uia-win.txt
index f2a8d1d32..e300dff9 100644
--- a/content/test/data/accessibility/html/input-color-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-color-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox LocalizedControlType='color picker' Value.Value='100% red 60% green 0% blue'
+Document
+++Group IsControlElement=false
+++++Button LocalizedControlType='color picker' Value.Value='100% red 60% green 0% blue'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-date-expected-uia-win.txt b/content/test/data/accessibility/html/input-date-expected-uia-win.txt
index ba8a1975..024e44e3 100644
--- a/content/test/data/accessibility/html/input-date-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-date-expected-uia-win.txt
@@ -1,27 +1,27 @@
-document
-++group IsControlElement=false
-++++textbox LocalizedControlType='date picker'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
-++++++++++++description Name='09'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
-++++++++++++description Name='01'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
-++++++++++++description Name='2008'
-++++++button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++textbox LocalizedControlType='date picker' Name='When'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Month When' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
-++++++++++++description Name='09'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Day When' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
-++++++++++++description Name='01'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Year When' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
-++++++++++++description Name='2008'
-++++++button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+Document
+++Group IsControlElement=false
+++++Edit LocalizedControlType='date picker'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
+++++++++++++Text Name='09'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
+++++++++++++Text Name='01'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
+++++++++++++Text Name='2008'
+++++++Button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++Edit LocalizedControlType='date picker' Name='When'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Month When' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
+++++++++++++Text Name='09'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Day When' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
+++++++++++++Text Name='01'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Year When' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
+++++++++++++Text Name='2008'
+++++++Button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
 <-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-uia-win.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-uia-win.txt
index a347f9d..56c74508e 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-uia-win.txt
@@ -1,70 +1,71 @@
-document
-++group IsControlElement=false
-++++textbox LocalizedControlType='date picker'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
-++++++++++++description Name='09'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
-++++++++++++description Name='01'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
-++++++++++++description Name='2008'
-++++++button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++textbox LocalizedControlType='date picker'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
-++++++++++++description Name='09'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
-++++++++++++description Name='01'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
-++++++++++++description Name='2008'
-++++++button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++textbox LocalizedControlType='date picker' Name='Third date picker' ControllerFor='{document}'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Month Third date picker' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
-++++++++++++description Name='09'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Day Third date picker' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
-++++++++++++description Name='01'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Year Third date picker' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
-++++++++++++description Name='2008'
-++++++button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++++Name='Chrome Legacy Window' IsControlElement=false
-++++++++document
-++++++++++group
-++++++++++++group IsControlElement=false
-++++++++++++++group IsControlElement=false
-++++++++++++++++group IsControlElement=false
-++++++++++++++++++button Name='Show month selection panel'
-++++++++++++++++++++description IsControlElement=false
-++++++++++++++++++++img
-++++++++++++++++button Name='Show previous month'
-++++++++++++++++++img
-++++++++++++++++button Name='Show next month'
-++++++++++++++++++img
-++++++++++++++++grid Grid.ColumnCount=0 Grid.RowCount=0 Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='Su'
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='Mo'
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='Tu'
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='We'
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='Th'
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='Fr'
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++++description Name='Sa'
-++++++++++++++++++group IsControlElement=false
-++++++++++++++++++++group IsControlElement=false
-++++++++++++++++++button Name='Today'
+Document
+++Group IsControlElement=false
+++++Edit LocalizedControlType='date picker'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
+++++++++++++Text Name='09'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
+++++++++++++Text Name='01'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
+++++++++++++Text Name='2008'
+++++++Button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++Edit LocalizedControlType='date picker'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
+++++++++++++Text Name='09'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
+++++++++++++Text Name='01'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
+++++++++++++Text Name='2008'
+++++++Button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++Edit LocalizedControlType='date picker' Name='Third date picker' ControllerFor='{document}'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Month Third date picker' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
+++++++++++++Text Name='09'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Day Third date picker' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='01'
+++++++++++++Text Name='01'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Year Third date picker' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=2008.00 Value.Value='2008'
+++++++++++++Text Name='2008'
+++++++Button Name='Show date picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++++Pane Name='Chrome Legacy Window' IsControlElement=false
+++++++++Document
+++++++++++Group
+++++++++++++Group IsControlElement=false
+++++++++++++++Group IsControlElement=false
+++++++++++++++++Group IsControlElement=false
+++++++++++++++++++Button Name='Show month selection panel'
+++++++++++++++++++++Text IsControlElement=false
+++++++++++++++++++++Image
+++++++++++++++++Button Name='Show previous month'
+++++++++++++++++++Image
+++++++++++++++++Button Name='Show next month'
+++++++++++++++++++Image
+++++++++++++++++DataGrid Grid.ColumnCount=0 Grid.RowCount=0 Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='Su'
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='Mo'
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='Tu'
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='We'
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='Th'
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='Fr'
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++++Text Name='Sa'
+++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++++Group IsControlElement=false
+++++++++++++++++++Button Name='Today'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-datetime-expected-uia-win.txt b/content/test/data/accessibility/html/input-datetime-expected-uia-win.txt
index 1cb00f8..9abfb60 100644
--- a/content/test/data/accessibility/html/input-datetime-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-datetime-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++textbox Value.Value='1/1/2015 1:00AM'
-++++textbox Name='Launch' Value.Value='1/1/2015 1:00AM'
+Document
+++Group IsControlElement=false
+++++Edit Value.Value='1/1/2015 1:00AM'
+++++Edit Name='Launch' Value.Value='1/1/2015 1:00AM'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-datetime-local-expected-uia-win.txt b/content/test/data/accessibility/html/input-datetime-local-expected-uia-win.txt
index 5527fb0..73555b0c 100644
--- a/content/test/data/accessibility/html/input-datetime-local-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-datetime-local-expected-uia-win.txt
@@ -1,24 +1,24 @@
-document
-++group IsControlElement=false
-++++textbox LocalizedControlType='local date and time picker'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='mm'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='dd'
-++++++++++description Name='/'
-++++++++++spinbutton Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='yyyy'
-++++++++++description Name=' '
-++++++++++spinbutton Name='Hours' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='--'
-++++++++++description Name=':'
-++++++++++spinbutton Name='Minutes' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=59.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='--'
-++++++++++description Name=' '
-++++++++++spinbutton Name='AM/PM' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=2.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='--'
-++++++button Name='Show local date and time picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+Document
+++Group IsControlElement=false
+++++Edit LocalizedControlType='local date and time picker'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='mm'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Day' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=31.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='dd'
+++++++++++Text Name='/'
+++++++++++Spinner Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='yyyy'
+++++++++++Text Name=' '
+++++++++++Spinner Name='Hours' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='--'
+++++++++++Text Name=':'
+++++++++++Spinner Name='Minutes' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=59.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='--'
+++++++++++Text Name=' '
+++++++++++Spinner Name='AM/PM' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=2.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='--'
+++++++Button Name='Show local date and time picker' ExpandCollapse.ExpandCollapseState='Collapsed'
 <-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-email-expected-uia-win.txt b/content/test/data/accessibility/html/input-email-expected-uia-win.txt
index 80ddd33..a75ec01 100644
--- a/content/test/data/accessibility/html/input-email-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-email-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document LocalizedControlType='document'
-++group LocalizedControlType='group' IsControlElement=false
-++++textbox LocalizedControlType='email' Value.Value='someone@example.com'
+Document LocalizedControlType='document'
+++Group LocalizedControlType='group' IsControlElement=false
+++++Edit LocalizedControlType='email' Value.Value='someone@example.com'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-file-expected-uia-win.txt b/content/test/data/accessibility/html/input-file-expected-uia-win.txt
index fad5021..1e0b340 100644
--- a/content/test/data/accessibility/html/input-file-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-file-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++button Name='Choose File'
-++++++button Name='Choose File'
+Document
+++Group IsControlElement=false
+++++Button Name='Choose File'
+++++++Button Name='Choose File'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-image-expected-uia-win.txt b/content/test/data/accessibility/html/input-image-expected-uia-win.txt
index a2471e57..7801cb85 100644
--- a/content/test/data/accessibility/html/input-image-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-image-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++button Name='Submit'
+Document
+++Group IsControlElement=false
+++++Button Name='Submit'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-list-expected-uia-win.txt b/content/test/data/accessibility/html/input-list-expected-uia-win.txt
index 4d5bd60..f671924 100644
--- a/content/test/data/accessibility/html/input-list-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-list-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description
-++++++description Name='Choose a pokemon '
-++++++combobox Name='Choose a pokemon' ExpandCollapse.ExpandCollapseState='LeafNode'
+Document
+++Group IsControlElement=false
+++++Text
+++++++Text Name='Choose a pokemon '
+++++++ComboBox Name='Choose a pokemon' ExpandCollapse.ExpandCollapseState='LeafNode'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-number-expected-uia-win.txt b/content/test/data/accessibility/html/input-number-expected-uia-win.txt
index ed54c734c..45cdd54c 100644
--- a/content/test/data/accessibility/html/input-number-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-number-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++spinbutton RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=1.00 Value.Value='1'
-++++spinbutton RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=10.00 RangeValue.Minimum=5.00 RangeValue.Value=6.00 Value.Value='6'
+Document
+++Group IsControlElement=false
+++++Spinner RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=1.00 Value.Value='1'
+++++Spinner RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=10.00 RangeValue.Minimum=5.00 RangeValue.Value=6.00 Value.Value='6'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-password-expected-uia-win.txt b/content/test/data/accessibility/html/input-password-expected-uia-win.txt
index aa6e4faa..ce0730e5 100644
--- a/content/test/data/accessibility/html/input-password-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-password-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox IsPassword=true Value.Value='••••••'
+Document
+++Group IsControlElement=false
+++++Edit IsPassword=true Value.Value='••••••'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-radio-checkbox-label-expected-uia-win.txt b/content/test/data/accessibility/html/input-radio-checkbox-label-expected-uia-win.txt
index e2d2c61..cc92e69d 100644
--- a/content/test/data/accessibility/html/input-radio-checkbox-label-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-radio-checkbox-label-expected-uia-win.txt
@@ -1,12 +1,13 @@
-document
-++group IsControlElement=false
-++++radio Name='label ignored for radio button' SelectionItem.IsSelected=false
-++++checkbox Name='label ignored for checkbox' Toggle.ToggleState='Off'
-++++description Name='label exposed for radio button '
-++++++description Name='label exposed for radio button '
-++++++radio Name='label exposed for radio button' SelectionItem.IsSelected=false
-++++++description Name=' '
-++++description Name='label exposed for checkbox '
-++++++description Name='label exposed for checkbox '
-++++++checkbox Name='label exposed for checkbox' Toggle.ToggleState='Off'
-++++++description Name=' '
+Document
+++Group IsControlElement=false
+++++RadioButton Name='label ignored for radio button' SelectionItem.IsSelected=false
+++++CheckBox Name='label ignored for checkbox' Toggle.ToggleState='Off'
+++++Text Name='label exposed for radio button '
+++++++Text Name='label exposed for radio button '
+++++++RadioButton Name='label exposed for radio button' SelectionItem.IsSelected=false
+++++++Text Name=' '
+++++Text Name='label exposed for checkbox '
+++++++Text Name='label exposed for checkbox '
+++++++CheckBox Name='label exposed for checkbox' Toggle.ToggleState='Off'
+++++++Text Name=' '
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-radio-expected-uia-win.txt b/content/test/data/accessibility/html/input-radio-expected-uia-win.txt
index f37c6de2..f14091e 100644
--- a/content/test/data/accessibility/html/input-radio-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-radio-expected-uia-win.txt
@@ -1,13 +1,14 @@
-document
-++form IsControlElement=false
-++++radio SelectionItem.IsSelected=false
-++++description Name='Radio1'
-++++separator Name='<newline>'
-++++radio SelectionItem.IsSelected=false
-++++description Name='Radio2'
-++form IsControlElement=false
-++++radio Name='Radio3' SelectionItem.IsSelected=false
-++++radio Name='Radio4' SelectionItem.IsSelected=true
-++form IsControlElement=false
-++++radio Name='Radio5' SelectionItem.IsSelected=false
-++++radio Name='Radio6' SelectionItem.IsSelected=true
+Document
+++Group IsControlElement=false
+++++RadioButton SelectionItem.IsSelected=false
+++++Text Name='Radio1'
+++++Separator Name='<newline>'
+++++RadioButton SelectionItem.IsSelected=false
+++++Text Name='Radio2'
+++Group IsControlElement=false
+++++RadioButton Name='Radio3' SelectionItem.IsSelected=false
+++++RadioButton Name='Radio4' SelectionItem.IsSelected=true
+++Group IsControlElement=false
+++++RadioButton Name='Radio5' SelectionItem.IsSelected=false
+++++RadioButton Name='Radio6' SelectionItem.IsSelected=true
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-radio-in-menu-expected-uia-win.txt b/content/test/data/accessibility/html/input-radio-in-menu-expected-uia-win.txt
index 69b28926..b08d816 100644
--- a/content/test/data/accessibility/html/input-radio-in-menu-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-radio-in-menu-expected-uia-win.txt
@@ -1,11 +1,12 @@
-document
-++group IsControlElement=false
-++++menuitemradio SelectionItem.IsSelected=true
-++++description Name='Radio0 '
-++++menuitemradio SelectionItem.IsSelected=false
-++++description Name='Radio1 '
-++++radio Name='Radio2' SelectionItem.IsSelected=false
-++menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++radio Name='Radio3' SelectionItem.IsSelected=false
-++++menuitemradio SelectionItem.IsSelected=false
-++++menuitemradio SelectionItem.IsSelected=true
+Document
+++Group IsControlElement=false
+++++RadioButton SelectionItem.IsSelected=true
+++++Text Name='Radio0 '
+++++RadioButton SelectionItem.IsSelected=false
+++++Text Name='Radio1 '
+++++RadioButton Name='Radio2' SelectionItem.IsSelected=false
+++Menu Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++RadioButton Name='Radio3' SelectionItem.IsSelected=false
+++++RadioButton SelectionItem.IsSelected=false
+++++RadioButton SelectionItem.IsSelected=true
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-range-expected-uia-win.txt b/content/test/data/accessibility/html/input-range-expected-uia-win.txt
index e6e29de..2ee0808e 100644
--- a/content/test/data/accessibility/html/input-range-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-range-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=10.00 RangeValue.Minimum=1.00 RangeValue.Value=5.00 Value.Value='5'
+Document
+++Group IsControlElement=false
+++++Slider RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=10.00 RangeValue.Minimum=1.00 RangeValue.Value=5.00 Value.Value='5'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-reset-expected-uia-win.txt b/content/test/data/accessibility/html/input-reset-expected-uia-win.txt
index 8a4121e9..90883b4 100644
--- a/content/test/data/accessibility/html/input-reset-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-reset-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++textbox
-++++button Name='Reset'
+Document
+++Group IsControlElement=false
+++++Edit
+++++Button Name='Reset'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-search-expected-uia-win.txt b/content/test/data/accessibility/html/input-search-expected-uia-win.txt
index a5039a1..4bd58fa3 100644
--- a/content/test/data/accessibility/html/input-search-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-search-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document LocalizedControlType='document'
-++group LocalizedControlType='group' IsControlElement=false
-++++searchbox LocalizedControlType='search box' Value.Value='Search terms'
+Document LocalizedControlType='document'
+++Group LocalizedControlType='group' IsControlElement=false
+++++Edit LocalizedControlType='search box' Value.Value='Search terms'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-submit-expected-uia-win.txt b/content/test/data/accessibility/html/input-submit-expected-uia-win.txt
index c51582c..55a1b26b 100644
--- a/content/test/data/accessibility/html/input-submit-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-submit-expected-uia-win.txt
@@ -1,14 +1,15 @@
-document
-++form IsControlElement=false
-++++textbox
-++++button Name='First submit in a form is a valid default button'
-++++button Name='Second submit in a form not a valid default button'
-++form IsControlElement=false
-++++textbox
-++++button Name='First image button in a form is a valid default button'
-++++++img
-++++++description Name='First image button in a form is a valid default button' IsControlElement=false
-++++button Name='Second image button in a form not a valid default button'
-++++++img
-++++++description Name='Second image button in a form not a valid default button' IsControlElement=false
-++button Name='Submit outside of form not a valid default button'
+Document
+++Group IsControlElement=false
+++++Edit
+++++Button Name='First submit in a form is a valid default button'
+++++Button Name='Second submit in a form not a valid default button'
+++Group IsControlElement=false
+++++Edit
+++++Button Name='First image button in a form is a valid default button'
+++++++Image
+++++++Text Name='First image button in a form is a valid default button' IsControlElement=false
+++++Button Name='Second image button in a form not a valid default button'
+++++++Image
+++++++Text Name='Second image button in a form not a valid default button' IsControlElement=false
+++Button Name='Submit outside of form not a valid default button'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-suggestions-source-element-expected-uia-win.txt b/content/test/data/accessibility/html/input-suggestions-source-element-expected-uia-win.txt
index f26bf694..9ca5a80a 100644
--- a/content/test/data/accessibility/html/input-suggestions-source-element-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-suggestions-source-element-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++combobox ExpandCollapse.ExpandCollapseState='LeafNode'
+Document
+++Group IsControlElement=false
+++++ComboBox ExpandCollapse.ExpandCollapseState='LeafNode'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-tel-expected-uia-win.txt b/content/test/data/accessibility/html/input-tel-expected-uia-win.txt
index 447c122..f3b5007 100644
--- a/content/test/data/accessibility/html/input-tel-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-tel-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document LocalizedControlType='document'
-++group LocalizedControlType='group' IsControlElement=false
-++++textbox LocalizedControlType='telephone' Value.Value='123-456-7890'
+Document LocalizedControlType='document'
+++Group LocalizedControlType='group' IsControlElement=false
+++++Edit LocalizedControlType='telephone' Value.Value='123-456-7890'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-text-expected-uia-win.txt b/content/test/data/accessibility/html/input-text-expected-uia-win.txt
index 1bb4c03..52e66a28 100644
--- a/content/test/data/accessibility/html/input-text-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-text-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox Name='Name'
+Document
+++Group IsControlElement=false
+++++Edit Name='Name'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt b/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt
index 73556fee..3be26c3 100644
--- a/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt
@@ -1,11 +1,12 @@
-document
-++textbox Name='Title0' HelpText='Title0'
-++textbox Name='Label1' HelpText='Title1'
-++textbox Name='AriaLabel2' HelpText='Title2'
-++textbox Name='LabelledBy3' HelpText='Title3'
-++textbox Name='Placeholder4' HelpText='Placeholder4'
-++textbox Name='ARIA Placeholder4a' HelpText='ARIA Placeholder4a'
-++textbox Name='Placeholder4b' HelpText='Placeholder4b'
-++textbox Name='Placeholder5' HelpText='Placeholder5'
-++textbox Name='LabelledBy6' HelpText='Title6'
-++textbox Name='AriaLabel7' HelpText='Placeholder7'
+Document
+++Edit Name='Title0' HelpText='Title0'
+++Edit Name='Label1' HelpText='Title1'
+++Edit Name='AriaLabel2' HelpText='Title2'
+++Edit Name='LabelledBy3' HelpText='Title3'
+++Edit Name='Placeholder4' HelpText='Placeholder4'
+++Edit Name='ARIA Placeholder4a' HelpText='ARIA Placeholder4a'
+++Edit Name='Placeholder4b' HelpText='Placeholder4b'
+++Edit Name='Placeholder5' HelpText='Placeholder5'
+++Edit Name='LabelledBy6' HelpText='Title6'
+++Edit Name='AriaLabel7' HelpText='Placeholder7'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-text-read-only-expected-uia-win.txt b/content/test/data/accessibility/html/input-text-read-only-expected-uia-win.txt
index 1bb4c03..52e66a28 100644
--- a/content/test/data/accessibility/html/input-text-read-only-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-text-read-only-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox Name='Name'
+Document
+++Group IsControlElement=false
+++++Edit Name='Name'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-text-value-expected-uia-win.txt b/content/test/data/accessibility/html/input-text-value-expected-uia-win.txt
index 95678c4..7dc1deb 100644
--- a/content/test/data/accessibility/html/input-text-value-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-text-value-expected-uia-win.txt
@@ -1,18 +1,19 @@
-document
-++group IsControlElement=false
-++++description
-++++++description Name='l1'
-++++textbox Name='l1'
-++++description
-++++++description Name='l2'
-++++textbox Name='l2' Value.Value='value'
-++++textbox Name='l2'
-++++textbox Name='l2' Value.Value='value  *'
-++++description
-++++++description Name='Email'
-++++group IsControlElement=false
-++++textbox Name='Email'
-++++textbox Name='Email' Value.Value='value'
-++++textbox Name='l5'
-++++textbox Name='l6' Value.Value='Value'
-++++textbox Name='Name' Value.Value='value'
+Document
+++Group IsControlElement=false
+++++Text
+++++++Text Name='l1'
+++++Edit Name='l1'
+++++Text
+++++++Text Name='l2'
+++++Edit Name='l2' Value.Value='value'
+++++Edit Name='l2'
+++++Edit Name='l2' Value.Value='value  *'
+++++Text
+++++++Text Name='Email'
+++++Group IsControlElement=false
+++++Edit Name='Email'
+++++Edit Name='Email' Value.Value='value'
+++++Edit Name='l5'
+++++Edit Name='l6' Value.Value='Value'
+++++Edit Name='Name' Value.Value='value'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-text-with-selection-expected-uia-win.txt b/content/test/data/accessibility/html/input-text-with-selection-expected-uia-win.txt
index 22407b9..418bb10 100644
--- a/content/test/data/accessibility/html/input-text-with-selection-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-text-with-selection-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox Value.Value='Selection'
+Document
+++Group IsControlElement=false
+++++Edit Value.Value='Selection'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-time-expected-uia-win.txt b/content/test/data/accessibility/html/input-time-expected-uia-win.txt
index 3740056..3755c37 100644
--- a/content/test/data/accessibility/html/input-time-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-time-expected-uia-win.txt
@@ -1,27 +1,27 @@
-document
-++group IsControlElement=false
-++++group
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Hours' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=12.00 Value.Value='12'
-++++++++++++description Name='12'
-++++++++++description Name=':'
-++++++++++spinbutton Name='Minutes' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=59.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00 Value.Value='00'
-++++++++++++description Name='00'
-++++++++++description Name=' '
-++++++++++spinbutton Name='AM/PM' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=2.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='AM'
-++++++++++++description Name='AM'
-++++++button Name='Show time picker' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++group Name='Breakfast'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++spinbutton Name='Hours Breakfast' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=12.00 Value.Value='12'
-++++++++++++description Name='12'
-++++++++++description Name=':'
-++++++++++spinbutton Name='Minutes Breakfast' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=59.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00 Value.Value='00'
-++++++++++++description Name='00'
-++++++++++description Name=' '
-++++++++++spinbutton Name='AM/PM Breakfast' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=2.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='AM'
-++++++++++++description Name='AM'
-++++++button Name='Show time picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+Document
+++Group IsControlElement=false
+++++Group
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Hours' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=12.00 Value.Value='12'
+++++++++++++Text Name='12'
+++++++++++Text Name=':'
+++++++++++Spinner Name='Minutes' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=59.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00 Value.Value='00'
+++++++++++++Text Name='00'
+++++++++++Text Name=' '
+++++++++++Spinner Name='AM/PM' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=2.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='AM'
+++++++++++++Text Name='AM'
+++++++Button Name='Show time picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++Group Name='Breakfast'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Spinner Name='Hours Breakfast' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=12.00 Value.Value='12'
+++++++++++++Text Name='12'
+++++++++++Text Name=':'
+++++++++++Spinner Name='Minutes Breakfast' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=59.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00 Value.Value='00'
+++++++++++++Text Name='00'
+++++++++++Text Name=' '
+++++++++++Spinner Name='AM/PM Breakfast' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=2.00 RangeValue.Minimum=1.00 RangeValue.Value=1.00 Value.Value='AM'
+++++++++++++Text Name='AM'
+++++++Button Name='Show time picker' ExpandCollapse.ExpandCollapseState='Collapsed'
 <-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-types-expected-uia-win.txt b/content/test/data/accessibility/html/input-types-expected-uia-win.txt
index ec59efe..2f83314 100644
--- a/content/test/data/accessibility/html/input-types-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-types-expected-uia-win.txt
@@ -1,52 +1,53 @@
-document
-++group IsControlElement=false
-++++description
-++++++description Name='Default: '
-++++++textbox Name='Default:'
-++++description
-++++++description Name='Button: '
-++++++button Name='Button:'
-++++checkbox Name='Checkbox:' Toggle.ToggleState='Off'
-++++description
-++++++description Name='Color: '
-++++++textbox Name='Color:' Value.Value='0% red 0% green 0% blue'
-++++description
-++++++description Name='Email: '
-++++++textbox Name='Email:'
-++++description
-++++++description Name='File: '
-++++++button Name='File:'
-++++++++button Name='Choose File'
-++++description
-++++++description Name='Image: '
-++++++button Name='Image:'
-++++++++img
-++++++++description Name='Submit' IsControlElement=false
-++++description
-++++++description Name='Number: '
-++++++spinbutton Name='Number:' RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
-++++description
-++++++description Name='Password: '
-++++++textbox Name='Password:' IsPassword=true
-++++radio Name='Radio:' SelectionItem.IsSelected=false
-++++description
-++++++description Name='Range: '
-++++++slider Name='Range:' RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=100.00 RangeValue.Minimum=0.00 RangeValue.Value=50.00 Value.Value='50'
-++++description
-++++++description Name='Reset: '
-++++++button Name='Reset:'
-++++description
-++++++description Name='Search: '
-++++++searchbox Name='Search:'
-++++description
-++++++description Name='Submit: '
-++++++button Name='Submit:'
-++++description
-++++++description Name='Tel: '
-++++++textbox Name='Tel:'
-++++description
-++++++description Name='Text: '
-++++++textbox Name='Text:'
-++++description
-++++++description Name='Url: '
-++++++textbox Name='Url:'
+Document
+++Group IsControlElement=false
+++++Text
+++++++Text Name='Default: '
+++++++Edit Name='Default:'
+++++Text
+++++++Text Name='Button: '
+++++++Button Name='Button:'
+++++CheckBox Name='Checkbox:' Toggle.ToggleState='Off'
+++++Text
+++++++Text Name='Color: '
+++++++Button Name='Color:' Value.Value='0% red 0% green 0% blue'
+++++Text
+++++++Text Name='Email: '
+++++++Edit Name='Email:'
+++++Text
+++++++Text Name='File: '
+++++++Button Name='File:'
+++++++++Button Name='Choose File'
+++++Text
+++++++Text Name='Image: '
+++++++Button Name='Image:'
+++++++++Image
+++++++++Text Name='Submit' IsControlElement=false
+++++Text
+++++++Text Name='Number: '
+++++++Spinner Name='Number:' RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
+++++Text
+++++++Text Name='Password: '
+++++++Edit Name='Password:' IsPassword=true
+++++RadioButton Name='Radio:' SelectionItem.IsSelected=false
+++++Text
+++++++Text Name='Range: '
+++++++Slider Name='Range:' RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=100.00 RangeValue.Minimum=0.00 RangeValue.Value=50.00 Value.Value='50'
+++++Text
+++++++Text Name='Reset: '
+++++++Button Name='Reset:'
+++++Text
+++++++Text Name='Search: '
+++++++Edit Name='Search:'
+++++Text
+++++++Text Name='Submit: '
+++++++Button Name='Submit:'
+++++Text
+++++++Text Name='Tel: '
+++++++Edit Name='Tel:'
+++++Text
+++++++Text Name='Text: '
+++++++Edit Name='Text:'
+++++Text
+++++++Text Name='Url: '
+++++++Edit Name='Url:'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-url-expected-uia-win.txt b/content/test/data/accessibility/html/input-url-expected-uia-win.txt
index 6999c1b..00454b26 100644
--- a/content/test/data/accessibility/html/input-url-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-url-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document LocalizedControlType='document'
-++group LocalizedControlType='group' IsControlElement=false
-++++textbox LocalizedControlType='url' Value.Value='example.com'
+Document LocalizedControlType='document'
+++Group LocalizedControlType='group' IsControlElement=false
+++++Edit LocalizedControlType='url' Value.Value='example.com'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/input-week-expected-uia-win.txt b/content/test/data/accessibility/html/input-week-expected-uia-win.txt
index 42fb037..7a93e8d 100644
--- a/content/test/data/accessibility/html/input-week-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-week-expected-uia-win.txt
@@ -1,13 +1,13 @@
-document
-++group IsControlElement=false
-++++textbox LocalizedControlType='week picker'
-++++++group IsControlElement=false
-++++++++group IsControlElement=false
-++++++++++description Name='Week '
-++++++++++spinbutton Name='Week' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=53.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='--'
-++++++++++description Name=', '
-++++++++++spinbutton Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
-++++++++++++description Name='----'
-++++++button Name='Show week picker' ExpandCollapse.ExpandCollapseState='Collapsed'
+Document
+++Group IsControlElement=false
+++++Edit LocalizedControlType='week picker'
+++++++Group IsControlElement=false
+++++++++Group IsControlElement=false
+++++++++++Text Name='Week '
+++++++++++Spinner Name='Week' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=53.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='--'
+++++++++++Text Name=', '
+++++++++++Spinner Name='Year' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=275760.00 RangeValue.Minimum=1.00 RangeValue.Value=0.00 Value.Value='0'
+++++++++++++Text Name='----'
+++++++Button Name='Show week picker' ExpandCollapse.ExpandCollapseState='Collapsed'
 <-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ins-expected-uia-win.txt b/content/test/data/accessibility/html/ins-expected-uia-win.txt
index 4a362e97..930cfb4 100644
--- a/content/test/data/accessibility/html/ins-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ins-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document
-++group IsControlElement=false
-++++description Name='My favorite browser is '
-++++group IsControlElement=false
-++++++description Name='ABC'
-++++description Name=' '
-++++group IsControlElement=false
-++++++description Name='Chrome'
-++++description Name='!'
+Document
+++Group IsControlElement=false
+++++Text Name='My favorite browser is '
+++++Group IsControlElement=false
+++++++Text Name='ABC'
+++++Text Name=' '
+++++Group IsControlElement=false
+++++++Text Name='Chrome'
+++++Text Name='!'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/label-expected-uia-win.txt b/content/test/data/accessibility/html/label-expected-uia-win.txt
index 99bafe4..1c39d278 100644
--- a/content/test/data/accessibility/html/label-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/label-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++description
-++++++description Name='Label'
+Document
+++Group IsControlElement=false
+++++Text
+++++++Text Name='Label'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/landmark-expected-uia-win.txt b/content/test/data/accessibility/html/landmark-expected-uia-win.txt
index 7162696..8d58982 100644
--- a/content/test/data/accessibility/html/landmark-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/landmark-expected-uia-win.txt
@@ -1,149 +1,150 @@
-document
-++banner
-++++description Name='This is a header element.'
-++complementary
-++++description Name='This is an aside element.'
-++group IsControlElement=false
-++++description Name='This is an address element.'
-++contentinfo
-++++description Name='This is a footer element.'
-++form IsControlElement=false
-++++description Name='This is a form element.'
-++main
-++++description Name='This is a main element.'
-++navigation
-++++description Name='This is a nav element.'
-++application
-++++description Name='This is an ARIA application landmark.'
-++banner
-++++description Name='This is an ARIA banner landmark.'
-++complementary
-++++description Name='This is an ARIA complementary landmark.'
-++contentinfo
-++++description Name='This is an ARIA contentinfo landmark.'
-++form
-++++description Name='This is an ARIA form landmark.'
-++main
-++++description Name='This is an ARIA main landmark.'
-++navigation
-++++description Name='This is an ARIA navigation landmark.'
-++search
-++++description Name='This is an ARIA search landmark.'
-++article
-++++group
-++++++description Name='This should NOT banner role.'
-++complementary
-++++group
-++++++description Name='This should NOT have banner role.'
-++navigation
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='Details'
-++group IsControlElement=false
-++++group
-++++++description Name='This should NOT have banner role.' IsControlElement=false
-++group
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++group
-++++++description Name='This should NOT have banner role.' IsControlElement=false
-++main
-++++group
-++++++description Name='This should NOT have banner role.'
-++article
-++++group
-++++++description Name='This should NOT banner role.'
-++complementary
-++++group
-++++++description Name='This should NOT have banner role.'
-++navigation
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='Details'
-++group IsControlElement=false
-++++group
-++++++description Name='This should NOT have banner role.' IsControlElement=false
-++group
-++++group
-++++++description Name='This should NOT have banner role.'
-++group
-++++description Name='This should NOT have banner role.'
-++main
-++++group
-++++++description Name='This should NOT have banner role.'
-++article
-++++group
-++++++description Name='This should NOT footer role.'
-++complementary
-++++group
-++++++description Name='This should NOT have footer role.'
-++navigation
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='Details'
-++group IsControlElement=false
-++++group
-++++++description Name='This should NOT have footer role.' IsControlElement=false
-++group
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++description Name='This should NOT have footer role.'
-++main
-++++group
-++++++description Name='This should NOT have footer role.'
-++article
-++++group
-++++++description Name='This should NOT footer role.'
-++complementary
-++++group
-++++++description Name='This should NOT have footer role.'
-++navigation
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
-++++++description Name='Details'
-++group IsControlElement=false
-++++group
-++++++description Name='This should NOT have footer role.' IsControlElement=false
-++group
-++++group
-++++++description Name='This should NOT have footer role.'
-++group
-++++group
-++++++description Name='This should NOT have footer role.' IsControlElement=false
-++main
-++++group
-++++++description Name='This should NOT have footer role.'
+Document
+++Group
+++++Text Name='This is a header element.'
+++Group
+++++Text Name='This is an aside element.'
+++Group IsControlElement=false
+++++Text Name='This is an address element.'
+++Group
+++++Text Name='This is a footer element.'
+++Group IsControlElement=false
+++++Text Name='This is a form element.'
+++Group
+++++Text Name='This is a main element.'
+++Group
+++++Text Name='This is a nav element.'
+++Pane
+++++Text Name='This is an ARIA application landmark.'
+++Group
+++++Text Name='This is an ARIA banner landmark.'
+++Group
+++++Text Name='This is an ARIA complementary landmark.'
+++Group
+++++Text Name='This is an ARIA contentinfo landmark.'
+++Group
+++++Text Name='This is an ARIA form landmark.'
+++Group
+++++Text Name='This is an ARIA main landmark.'
+++Group
+++++Text Name='This is an ARIA navigation landmark.'
+++Group
+++++Text Name='This is an ARIA search landmark.'
+++Group
+++++Group
+++++++Text Name='This should NOT banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='Details'
+++Group IsControlElement=false
+++++Group
+++++++Text Name='This should NOT have banner role.' IsControlElement=false
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.' IsControlElement=false
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='Details'
+++Group IsControlElement=false
+++++Group
+++++++Text Name='This should NOT have banner role.' IsControlElement=false
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have banner role.'
+++Group
+++++Group
+++++++Text Name='This should NOT footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='Details'
+++Group IsControlElement=false
+++++Group
+++++++Text Name='This should NOT have footer role.' IsControlElement=false
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Button Name='Details' ExpandCollapse.ExpandCollapseState='LeafNode'
+++++++Text Name='Details'
+++Group IsControlElement=false
+++++Group
+++++++Text Name='This should NOT have footer role.' IsControlElement=false
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.' IsControlElement=false
+++Group
+++++Group
+++++++Text Name='This should NOT have footer role.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/legend-expected-uia-win.txt b/content/test/data/accessibility/html/legend-expected-uia-win.txt
index 2f6b7fcb..cceb92b6 100644
--- a/content/test/data/accessibility/html/legend-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/legend-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document
-++form IsControlElement=false
-++++group Name='Browser Engines:'
-++++++description IsControlElement=false
-++++++++description Name='Browser Engines:' IsControlElement=false
-++++++description Name='Browser: ' IsControlElement=false
-++++++textbox
-++++++description Name=' Rendering Engine: ' IsControlElement=false
-++++++textbox
+Document
+++Group IsControlElement=false
+++++Group Name='Browser Engines:'
+++++++Text IsControlElement=false
+++++++++Text Name='Browser Engines:' IsControlElement=false
+++++++Text Name='Browser: ' IsControlElement=false
+++++++Edit
+++++++Text Name=' Rendering Engine: ' IsControlElement=false
+++++++Edit
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/li-expected-uia-win.txt b/content/test/data/accessibility/html/li-expected-uia-win.txt
index 76d345e..4c07ffe2 100644
--- a/content/test/data/accessibility/html/li-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/li-expected-uia-win.txt
@@ -1,14 +1,15 @@
-document
-++list
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Item 1' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Item 2' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Item 3' IsControlElement=false
+Document
+++List
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Item 1' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Item 2' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Item 3' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/link-inside-heading-expected-uia-win.txt b/content/test/data/accessibility/html/link-inside-heading-expected-uia-win.txt
index 58a041b..1ae6278 100644
--- a/content/test/data/accessibility/html/link-inside-heading-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/link-inside-heading-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++heading Name='Link In Heading'
-++++link Name='Link In Heading'
-++++++description Name='Link In Heading' IsControlElement=false
+Document
+++Text Name='Link In Heading'
+++++Hyperlink Name='Link In Heading'
+++++++Text Name='Link In Heading' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/list-expected-uia-win.txt b/content/test/data/accessibility/html/list-expected-uia-win.txt
index 0cc0286..f4d9449 100644
--- a/content/test/data/accessibility/html/list-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/list-expected-uia-win.txt
@@ -1,23 +1,24 @@
-document
-++list
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='tic' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='tac' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='toe' IsControlElement=false
-++list
-++++listitem
-++++++description Name='tic' IsControlElement=false
-++++description Name=' '
-++++listitem
-++++++description Name='tac' IsControlElement=false
-++++description Name=' '
-++++listitem
-++++++description Name='toe' IsControlElement=false
+Document
+++List
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='tic' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='tac' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='toe' IsControlElement=false
+++List
+++++ListItem
+++++++Text Name='tic' IsControlElement=false
+++++Text Name=' '
+++++ListItem
+++++++Text Name='tac' IsControlElement=false
+++++Text Name=' '
+++++ListItem
+++++++Text Name='toe' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win.txt b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win.txt
index 5765c174..ce62b08 100644
--- a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win.txt
@@ -1,15 +1,16 @@
-document PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=8 Level=0
-++++listitem PositionInSet=5 SizeOfSet=0 Level=1
-++++++description Name='Level 1, item 5 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++++listitem PositionInSet=6 SizeOfSet=0 Level=1
-++++++description Name='Level 1, item 6 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++++++list PositionInSet=0 SizeOfSet=7 Level=0
-++++++++listitem PositionInSet=6 SizeOfSet=0 Level=2
-++++++++++description Name='Level 2, item 6 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++++++++listitem PositionInSet=7 SizeOfSet=0 Level=2
-++++++++++description Name='Level 2, item 7 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++++listitem PositionInSet=7 SizeOfSet=2 Level=1
-++++++description Name='Level 1, item 7 of set size 2' PositionInSet=0 SizeOfSet=0 Level=0
-++++listitem PositionInSet=8 SizeOfSet=3 Level=1
-++++++description Name='Level 1, item 8 of set size 3' PositionInSet=0 SizeOfSet=0 Level=0
+Document PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=8 Level=0
+++++ListItem PositionInSet=5 SizeOfSet=0 Level=1
+++++++Text Name='Level 1, item 5 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++++ListItem PositionInSet=6 SizeOfSet=0 Level=1
+++++++Text Name='Level 1, item 6 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++++++List PositionInSet=0 SizeOfSet=7 Level=0
+++++++++ListItem PositionInSet=6 SizeOfSet=0 Level=2
+++++++++++Text Name='Level 2, item 6 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++++++++ListItem PositionInSet=7 SizeOfSet=0 Level=2
+++++++++++Text Name='Level 2, item 7 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++++ListItem PositionInSet=7 SizeOfSet=2 Level=1
+++++++Text Name='Level 1, item 7 of set size 2' PositionInSet=0 SizeOfSet=0 Level=0
+++++ListItem PositionInSet=8 SizeOfSet=3 Level=1
+++++++Text Name='Level 1, item 8 of set size 3' PositionInSet=0 SizeOfSet=0 Level=0
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win7.txt b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win7.txt
index abfa92d..5a91cb4 100644
--- a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win7.txt
+++ b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-uia-win7.txt
@@ -1,15 +1,16 @@
-document
-++list
-++++listitem
-++++++description Name='Level 1, item 5 of set size unknown'
-++++listitem
-++++++description Name='Level 1, item 6 of set size unknown'
-++++++list
-++++++++listitem
-++++++++++description Name='Level 2, item 6 of set size unknown'
-++++++++listitem
-++++++++++description Name='Level 2, item 7 of set size unknown'
-++++listitem
-++++++description Name='Level 1, item 7 of set size 2'
-++++listitem
-++++++description Name='Level 1, item 8 of set size 3'
+Document
+++List
+++++ListItem
+++++++Text Name='Level 1, item 5 of set size unknown'
+++++ListItem
+++++++Text Name='Level 1, item 6 of set size unknown'
+++++++List
+++++++++ListItem
+++++++++++Text Name='Level 2, item 6 of set size unknown'
+++++++++ListItem
+++++++++++Text Name='Level 2, item 7 of set size unknown'
+++++ListItem
+++++++Text Name='Level 1, item 7 of set size 2'
+++++ListItem
+++++++Text Name='Level 1, item 8 of set size 3'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win.txt b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win.txt
index e616d5d..64ff21399 100644
--- a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win.txt
@@ -1,32 +1,33 @@
-document PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=1 Level=0
-++++listitem PositionInSet=1 SizeOfSet=0 Level=1
-++++++description Name='Level 1, item 1 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=1 Level=0
-++++listitem PositionInSet=1 SizeOfSet=0 Level=2
-++++++description Name='++Level 2, item 1 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=2 Level=0
-++++listitem PositionInSet=2 SizeOfSet=0 Level=2
-++++++description Name='++Level 2, item 2 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=3 Level=0
-++++listitem PositionInSet=3 SizeOfSet=0 Level=2
-++++++description Name='++Level 2, item 3 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=1 Level=0
-++++listitem PositionInSet=1 SizeOfSet=0 Level=3
-++++++description Name='++++Level 3, item 1 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=2 Level=0
-++++listitem PositionInSet=2 SizeOfSet=0 Level=3
-++++++description Name='++++Level 3, item 2 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=2 Level=0
-++++listitem PositionInSet=2 SizeOfSet=0 Level=1
-++++++description Name='Level 1, item 2 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=3 Level=0
-++++listitem PositionInSet=3 SizeOfSet=0 Level=1
-++++++description Name='Level 1, item 3 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
-++list PositionInSet=0 SizeOfSet=0 Level=0
-++++list PositionInSet=0 SizeOfSet=4 Level=0
-++++++listitem PositionInSet=4 SizeOfSet=4 Level=2
-++++++++description Name='Level Unspecified, aria-setsize attribute does not exist, item 4 of set size 4' PositionInSet=0 SizeOfSet=0 Level=0
-++++list PositionInSet=0 SizeOfSet=5 Level=0
-++++++listitem PositionInSet=5 SizeOfSet=5 Level=2
-++++++++description Name='Level Unspecified, aria-setsize attribute does not exist, item 5 of set size 5' PositionInSet=0 SizeOfSet=0 Level=0
+Document PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=1 Level=0
+++++ListItem PositionInSet=1 SizeOfSet=0 Level=1
+++++++Text Name='Level 1, item 1 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=1 Level=0
+++++ListItem PositionInSet=1 SizeOfSet=0 Level=2
+++++++Text Name='++Level 2, item 1 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=2 Level=0
+++++ListItem PositionInSet=2 SizeOfSet=0 Level=2
+++++++Text Name='++Level 2, item 2 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=3 Level=0
+++++ListItem PositionInSet=3 SizeOfSet=0 Level=2
+++++++Text Name='++Level 2, item 3 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=1 Level=0
+++++ListItem PositionInSet=1 SizeOfSet=0 Level=3
+++++++Text Name='++++Level 3, item 1 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=2 Level=0
+++++ListItem PositionInSet=2 SizeOfSet=0 Level=3
+++++++Text Name='++++Level 3, item 2 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=2 Level=0
+++++ListItem PositionInSet=2 SizeOfSet=0 Level=1
+++++++Text Name='Level 1, item 2 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=3 Level=0
+++++ListItem PositionInSet=3 SizeOfSet=0 Level=1
+++++++Text Name='Level 1, item 3 of set size unknown' PositionInSet=0 SizeOfSet=0 Level=0
+++List PositionInSet=0 SizeOfSet=0 Level=0
+++++List PositionInSet=0 SizeOfSet=4 Level=0
+++++++ListItem PositionInSet=4 SizeOfSet=4 Level=2
+++++++++Text Name='Level Unspecified, aria-setsize attribute does not exist, item 4 of set size 4' PositionInSet=0 SizeOfSet=0 Level=0
+++++List PositionInSet=0 SizeOfSet=5 Level=0
+++++++ListItem PositionInSet=5 SizeOfSet=5 Level=2
+++++++++Text Name='Level Unspecified, aria-setsize attribute does not exist, item 5 of set size 5' PositionInSet=0 SizeOfSet=0 Level=0
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win7.txt b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win7.txt
index c6330429..018941b 100644
--- a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win7.txt
+++ b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-uia-win7.txt
@@ -1,32 +1,33 @@
-document
-++list
-++++listitem
-++++++description Name='Level 1, item 1 of set size unknown'
-++list
-++++listitem
-++++++description Name='++Level 2, item 1 of set size unknown'
-++list
-++++listitem
-++++++description Name='++Level 2, item 2 of set size unknown'
-++list
-++++listitem
-++++++description Name='++Level 2, item 3 of set size unknown'
-++list
-++++listitem
-++++++description Name='++++Level 3, item 1 of set size unknown'
-++list
-++++listitem
-++++++description Name='++++Level 3, item 2 of set size unknown'
-++list
-++++listitem
-++++++description Name='Level 1, item 2 of set size unknown'
-++list
-++++listitem
-++++++description Name='Level 1, item 3 of set size unknown'
-++list
-++++list
-++++++listitem
-++++++++description Name='Level Unspecified, aria-setsize attribute does not exist, item 4 of set size 4'
-++++list
-++++++listitem
-++++++++description Name='Level Unspecified, aria-setsize attribute does not exist, item 5 of set size 5'
+Document
+++List
+++++ListItem
+++++++Text Name='Level 1, item 1 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='++Level 2, item 1 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='++Level 2, item 2 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='++Level 2, item 3 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='++++Level 3, item 1 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='++++Level 3, item 2 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='Level 1, item 2 of set size unknown'
+++List
+++++ListItem
+++++++Text Name='Level 1, item 3 of set size unknown'
+++List
+++++List
+++++++ListItem
+++++++++Text Name='Level Unspecified, aria-setsize attribute does not exist, item 4 of set size 4'
+++++List
+++++++ListItem
+++++++++Text Name='Level Unspecified, aria-setsize attribute does not exist, item 5 of set size 5'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/list-markers-expected-uia-win.txt b/content/test/data/accessibility/html/list-markers-expected-uia-win.txt
index a0819e8c..1f5bdd0 100644
--- a/content/test/data/accessibility/html/list-markers-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/list-markers-expected-uia-win.txt
@@ -1,20 +1,21 @@
-document
-++list
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='First item properly groups itself despite ' IsControlElement=false
-++++++description Name='bolded' IsControlElement=false
-++++++description Name=' text.' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='This should also be ' IsControlElement=false
-++++++description Name='seen' IsControlElement=false
-++++++description Name=' as a group.' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Some ' IsControlElement=false
-++++++description Name='more' IsControlElement=false
-++++++description Name=' text.' IsControlElement=false
+Document
+++List
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='First item properly groups itself despite ' IsControlElement=false
+++++++Text Name='bolded' IsControlElement=false
+++++++Text Name=' text.' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='This should also be ' IsControlElement=false
+++++++Text Name='seen' IsControlElement=false
+++++++Text Name=' as a group.' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Some ' IsControlElement=false
+++++++Text Name='more' IsControlElement=false
+++++++Text Name=' text.' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/main-expected-uia-win.txt b/content/test/data/accessibility/html/main-expected-uia-win.txt
index 6ebd73b..4c58089 100644
--- a/content/test/data/accessibility/html/main-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/main-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++main
-++++description Name='This is main element.'
-++main
-++++description Name='This is an ARIA role main.'
+Document
+++Group
+++++Text Name='This is main element.'
+++Group
+++++Text Name='This is an ARIA role main.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/mark-expected-uia-win.txt b/content/test/data/accessibility/html/mark-expected-uia-win.txt
index 88eacb14..93247766 100644
--- a/content/test/data/accessibility/html/mark-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/mark-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++description Name='This test is to check '
-++++description LocalizedControlType='highlight' IsControlElement=false
-++++++description Name='mark tag'
-++++description Name='.'
+Document
+++Group IsControlElement=false
+++++Text Name='This test is to check '
+++++Text LocalizedControlType='highlight' IsControlElement=false
+++++++Text Name='mark tag'
+++++Text Name='.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/math-expected-uia-win.txt b/content/test/data/accessibility/html/math-expected-uia-win.txt
index a9c5d1f..ce60f2c 100644
--- a/content/test/data/accessibility/html/math-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/math-expected-uia-win.txt
@@ -1,10 +1,11 @@
-document
-++group IsControlElement=false
-++++group IsControlElement=false
-++++++description Name='a'
-++++++description Name='2'
-++++group IsControlElement=false
-++++++description Name='+'
-++++group IsControlElement=false
-++++++description Name='b'
-++++++description Name='2'
+Document
+++Group IsControlElement=false
+++++Group IsControlElement=false
+++++++Text Name='a'
+++++++Text Name='2'
+++++Group IsControlElement=false
+++++++Text Name='+'
+++++Group IsControlElement=false
+++++++Text Name='b'
+++++++Text Name='2'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/meter-expected-uia-win.txt b/content/test/data/accessibility/html/meter-expected-uia-win.txt
index bcedef1..d3f72020 100644
--- a/content/test/data/accessibility/html/meter-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/meter-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document LocalizedControlType='document'
-++group LocalizedControlType='group' IsControlElement=false
-++++progressbar LocalizedControlType='meter' RangeValue.IsReadOnly=true RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=10.00 RangeValue.Minimum=1.00 RangeValue.Value=2.00 Value.Value='2'
+Document LocalizedControlType='document'
+++Group LocalizedControlType='group' IsControlElement=false
+++++ProgressBar LocalizedControlType='meter' RangeValue.IsReadOnly=true RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=10.00 RangeValue.Minimum=1.00 RangeValue.Value=2.00 Value.Value='2'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/modal-dialog-closed-expected-uia-win.txt b/content/test/data/accessibility/html/modal-dialog-closed-expected-uia-win.txt
index 084444e..5945bae 100644
--- a/content/test/data/accessibility/html/modal-dialog-closed-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-closed-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++description Name='Test that elements respawn in the accessibility tree after a modal dialog closes.'
-++group
-++++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='This should be in the tree.'
-++++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++++listitem Name='This should be in the tree.' SelectionItem.IsSelected=true
-++textbox Value.Value='0% red 0% green 0% blue'
+Document
+++Text Name='Test that elements respawn in the accessibility tree after a modal dialog closes.'
+++Group
+++++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='This should be in the tree.'
+++++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++++ListItem Name='This should be in the tree.' SelectionItem.IsSelected=true
+++Button Value.Value='0% red 0% green 0% blue'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt
index 4baecbb..f1bfb14 100644
--- a/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++dialog IsControlElement=false Window.IsModal=true
-++++description Name='The dialog subtree should be the only text content in the accessibility tree. '
-++++link Name='Link inside the dialog.'
-++++++description Name='Link inside the dialog.' IsControlElement=false
+Document
+++Group IsControlElement=false
+++Pane IsControlElement=false Window.IsModal=true
+++++Text Name='The dialog subtree should be the only text content in the accessibility tree. '
+++++Hyperlink Name='Link inside the dialog.'
+++++++Text Name='Link inside the dialog.' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt b/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt
index 15f808d..164f0dbbbd 100644
--- a/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++dialog IsControlElement=false Window.IsModal=true
-++++description Name='This is the now active dialog. Of course it should be in the tree. '
-++++button Name='This is in the active dialog and should be in the tree.'
+Document
+++Group IsControlElement=false
+++Pane IsControlElement=false Window.IsModal=true
+++++Text Name='This is the now active dialog. Of course it should be in the tree. '
+++++Button Name='This is in the active dialog and should be in the tree.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/navigation-expected-uia-win.txt b/content/test/data/accessibility/html/navigation-expected-uia-win.txt
index 3c8e763..a73a099a 100644
--- a/content/test/data/accessibility/html/navigation-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/navigation-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++navigation
-++++link Name='Don't click on me'
-++++++description Name='Don't click on me' IsControlElement=false
+Document
+++Group
+++++Hyperlink Name='Don't click on me'
+++++++Text Name='Don't click on me' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/node-changed-crash-in-editable-text-expected-uia-win.txt b/content/test/data/accessibility/html/node-changed-crash-in-editable-text-expected-uia-win.txt
index 10ae582..7ca663b 100644
--- a/content/test/data/accessibility/html/node-changed-crash-in-editable-text-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/node-changed-crash-in-editable-text-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group Name='Done'
-++++group
-++++group
+Document
+++Group Name='Done'
+++++Group
+++++Group
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/object-expected-uia-win.txt b/content/test/data/accessibility/html/object-expected-uia-win.txt
index 8cf75072..8a379cf 100644
--- a/content/test/data/accessibility/html/object-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/object-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++document
+Document
+++Group IsControlElement=false
+++++Document
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/offscreen-iframe-expected-uia-win.txt b/content/test/data/accessibility/html/offscreen-iframe-expected-uia-win.txt
index 9f43eb2..f989df8 100644
--- a/content/test/data/accessibility/html/offscreen-iframe-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/offscreen-iframe-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++document
-++++++document
-++++++++group Name='iframe_onscreen'
-++++++++group Name='iframe_offscreen'
+Document
+++Group IsControlElement=false
+++++Document
+++++++Document
+++++++++Group Name='iframe_onscreen'
+++++++++Group Name='iframe_offscreen'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/offscreen-select-expected-uia-win.txt b/content/test/data/accessibility/html/offscreen-select-expected-uia-win.txt
index c7fc3e5..78ec07d 100644
--- a/content/test/data/accessibility/html/offscreen-select-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/offscreen-select-expected-uia-win.txt
@@ -1,11 +1,12 @@
-document
-++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Onscreen 1'
-++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++listitem Name='Onscreen 1' SelectionItem.IsSelected=true
-++++++listitem Name='Onscreen 2' SelectionItem.IsSelected=false
-++++++listitem Name='Onscreen 3' SelectionItem.IsSelected=false
-++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Offscreen 1'
-++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++listitem Name='Offscreen 1' SelectionItem.IsSelected=true
-++++++listitem Name='Offscreen 2' SelectionItem.IsSelected=false
-++++++listitem Name='Offscreen 3' SelectionItem.IsSelected=false
+Document
+++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Onscreen 1'
+++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++ListItem Name='Onscreen 1' SelectionItem.IsSelected=true
+++++++ListItem Name='Onscreen 2' SelectionItem.IsSelected=false
+++++++ListItem Name='Onscreen 3' SelectionItem.IsSelected=false
+++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Offscreen 1'
+++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++ListItem Name='Offscreen 1' SelectionItem.IsSelected=true
+++++++ListItem Name='Offscreen 2' SelectionItem.IsSelected=false
+++++++ListItem Name='Offscreen 3' SelectionItem.IsSelected=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ol-expected-uia-win.txt b/content/test/data/accessibility/html/ol-expected-uia-win.txt
index d372e7f7..2c3aa2dd 100644
--- a/content/test/data/accessibility/html/ol-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ol-expected-uia-win.txt
@@ -1,27 +1,28 @@
-document
-++list
-++++listitem
-++++++group
-++++++++description Name='1. ' IsControlElement=false
-++++++description Name='Chrome' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='2. ' IsControlElement=false
-++++++description Name='Safari' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='3. ' IsControlElement=false
-++++++description Name='IE' IsControlElement=false
-++list
-++++listitem
-++++++group
-++++++++description Name='10. ' IsControlElement=false
-++++++description Name='Android' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='11. ' IsControlElement=false
-++++++description Name='Mac' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='12. ' IsControlElement=false
-++++++description Name='Windows' IsControlElement=false
+Document
+++List
+++++ListItem
+++++++Group
+++++++++Text Name='1. ' IsControlElement=false
+++++++Text Name='Chrome' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='2. ' IsControlElement=false
+++++++Text Name='Safari' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='3. ' IsControlElement=false
+++++++Text Name='IE' IsControlElement=false
+++List
+++++ListItem
+++++++Group
+++++++++Text Name='10. ' IsControlElement=false
+++++++Text Name='Android' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='11. ' IsControlElement=false
+++++++Text Name='Mac' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='12. ' IsControlElement=false
+++++++Text Name='Windows' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/optgroup-expected-uia-win.txt b/content/test/data/accessibility/html/optgroup-expected-uia-win.txt
index 30dfbaaa..2cb7b26d 100644
--- a/content/test/data/accessibility/html/optgroup-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/optgroup-expected-uia-win.txt
@@ -1,15 +1,16 @@
-document
-++group IsControlElement=false
-++++listbox Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false Value.IsReadOnly=false
-++++++group Name='Enabled'
-++++++++description Name='Enabled' IsControlElement=false
-++++++option Name='One' SelectionItem.IsSelected=false
-++++++option Name='Two' SelectionItem.IsSelected=false
-++++++option Name='Three' SelectionItem.IsSelected=false
-++++++option Name='Four' SelectionItem.IsSelected=false
-++++++group Name='Disabled'
-++++++++description Name='Disabled' IsControlElement=false
-++++++option Name='One' IsEnabled=false
-++++++option Name='Two' IsEnabled=false
-++++++option Name='Three' IsEnabled=false
-++++++option Name='Four' IsEnabled=false
+Document
+++Group IsControlElement=false
+++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false Value.IsReadOnly=false
+++++++Group Name='Enabled'
+++++++++Text Name='Enabled' IsControlElement=false
+++++++ListItem Name='One' SelectionItem.IsSelected=false
+++++++ListItem Name='Two' SelectionItem.IsSelected=false
+++++++ListItem Name='Three' SelectionItem.IsSelected=false
+++++++ListItem Name='Four' SelectionItem.IsSelected=false
+++++++Group Name='Disabled'
+++++++++Text Name='Disabled' IsControlElement=false
+++++++ListItem Name='One' IsEnabled=false
+++++++ListItem Name='Two' IsEnabled=false
+++++++ListItem Name='Three' IsEnabled=false
+++++++ListItem Name='Four' IsEnabled=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/output-expected-uia-win.txt b/content/test/data/accessibility/html/output-expected-uia-win.txt
index d88144d..8c4c31d8 100644
--- a/content/test/data/accessibility/html/output-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/output-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++form IsControlElement=false
-++++spinbutton RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
-++++description Name=' + '
-++++spinbutton RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
-++++description Name=' ='
-++++status LocalizedControlType='output' IsControlElement=false
+Document
+++Group IsControlElement=false
+++++Spinner RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
+++++Text Name=' + '
+++++Spinner RangeValue.IsReadOnly=false RangeValue.LargeChange=10.00 RangeValue.SmallChange=1.00 RangeValue.Maximum=0.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
+++++Text Name=' ='
+++++StatusBar LocalizedControlType='output' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/p-expected-uia-win.txt b/content/test/data/accessibility/html/p-expected-uia-win.txt
index ee12578..f0bda32 100644
--- a/content/test/data/accessibility/html/p-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/p-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++description Name='Before'
-++group IsControlElement=false
-++++description Name='Paragraph'
-++description Name='After'
+Document
+++Text Name='Before'
+++Group IsControlElement=false
+++++Text Name='Paragraph'
+++Text Name='After'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/portal-expected-uia-win.txt b/content/test/data/accessibility/html/portal-expected-uia-win.txt
index 759296a..ed6bd9c 100644
--- a/content/test/data/accessibility/html/portal-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/portal-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++description Name='Before portal'
-++button Name='portal'
-++group IsControlElement=false
-++++description Name='After portal'
+Document
+++Group IsControlElement=false
+++++Text Name='Before portal'
+++Button Name='portal'
+++Group IsControlElement=false
+++++Text Name='After portal'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/pre-expected-uia-win.txt b/content/test/data/accessibility/html/pre-expected-uia-win.txt
index 703295d..b2a6f5f 100644
--- a/content/test/data/accessibility/html/pre-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/pre-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document
-++region IsControlElement=false
-++++description Name='This test is to check   pre<newline>formatting.'
-++group IsControlElement=false
-++++description Name='This test is to check   pre<newline>formatting'
-++group IsControlElement=false
-++++description Name='This test is to check   pre<newline>formatting.'
-++group IsControlElement=false
-++++description Name='This test is to check pre formatting.'
+Document
+++Pane IsControlElement=false
+++++Text Name='This test is to check   pre<newline>formatting.'
+++Group IsControlElement=false
+++++Text Name='This test is to check   pre<newline>formatting'
+++Group IsControlElement=false
+++++Text Name='This test is to check   pre<newline>formatting.'
+++Group IsControlElement=false
+++++Text Name='This test is to check pre formatting.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/progress-expected-uia-win.txt b/content/test/data/accessibility/html/progress-expected-uia-win.txt
index dc16673..3c2af83 100644
--- a/content/test/data/accessibility/html/progress-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/progress-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++progressbar RangeValue.IsReadOnly=true RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=100.00 RangeValue.Minimum=0.00 RangeValue.Value=22.00 Value.Value='22'
-++++progressbar RangeValue.IsReadOnly=true RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=1.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
+Document
+++Group IsControlElement=false
+++++ProgressBar RangeValue.IsReadOnly=true RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=100.00 RangeValue.Minimum=0.00 RangeValue.Value=22.00 Value.Value='22'
+++++ProgressBar RangeValue.IsReadOnly=true RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=1.00 RangeValue.Minimum=0.00 RangeValue.Value=0.00
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/q-expected-uia-win.txt b/content/test/data/accessibility/html/q-expected-uia-win.txt
index 47b3b84e2..7fb9316 100644
--- a/content/test/data/accessibility/html/q-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/q-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++group IsControlElement=false
-++++description Name='This is '
-++++description Name='"'
-++++description Name='Chromium Blink'
-++++description Name='"'
-++++description Name=' based browser.'
+Document
+++Group IsControlElement=false
+++++Text Name='This is '
+++++Text Name='"'
+++++Text Name='Chromium Blink'
+++++Text Name='"'
+++++Text Name=' based browser.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ruby-expected-uia-win.txt b/content/test/data/accessibility/html/ruby-expected-uia-win.txt
index 18ff2fb..54296ed 100644
--- a/content/test/data/accessibility/html/ruby-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ruby-expected-uia-win.txt
@@ -1,6 +1,7 @@
-document
-++group IsControlElement=false
-++++region IsControlElement=false
-++++++description IsControlElement=false
-++++++++description Name='ruby text'
-++++++description Name='ruby base'
+Document
+++Group IsControlElement=false
+++++Pane IsControlElement=false
+++++++Text IsControlElement=false
+++++++++Text Name='ruby text'
+++++++Text Name='ruby base'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/scrollable-expected-uia-win.txt b/content/test/data/accessibility/html/scrollable-expected-uia-win.txt
index c7cd62b..0aa0f99b 100644
--- a/content/test/data/accessibility/html/scrollable-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/scrollable-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document Scroll.HorizontalScrollPercent=-1.00 Scroll.HorizontalViewSize=100.00 Scroll.HorizontallyScrollable=false Scroll.VerticalScrollPercent=-1.00 Scroll.VerticalViewSize=100.00 Scroll.VerticallyScrollable=false
-++group Name='not'
-++++description Name='not scrollable'
-++group Name='x' Scroll.HorizontalScrollPercent=0.00 Scroll.HorizontalViewSize=50.00 Scroll.HorizontallyScrollable=true Scroll.VerticalScrollPercent=-1.00 Scroll.VerticalViewSize=100.00 Scroll.VerticallyScrollable=false
-++group Name='y' Scroll.HorizontalScrollPercent=-1.00 Scroll.HorizontalViewSize=100.00 Scroll.HorizontallyScrollable=false Scroll.VerticalScrollPercent=0.00 Scroll.VerticalViewSize=50.00 Scroll.VerticallyScrollable=true
+Document Scroll.HorizontalScrollPercent=-1.00 Scroll.HorizontalViewSize=100.00 Scroll.HorizontallyScrollable=false Scroll.VerticalScrollPercent=-1.00 Scroll.VerticalViewSize=100.00 Scroll.VerticallyScrollable=false
+++Group Name='not'
+++++Text Name='not scrollable'
+++Group Name='x' Scroll.HorizontalScrollPercent=0.00 Scroll.HorizontalViewSize=50.00 Scroll.HorizontallyScrollable=true Scroll.VerticalScrollPercent=-1.00 Scroll.VerticalViewSize=100.00 Scroll.VerticallyScrollable=false
+++Group Name='y' Scroll.HorizontalScrollPercent=-1.00 Scroll.HorizontalViewSize=100.00 Scroll.HorizontallyScrollable=false Scroll.VerticalScrollPercent=0.00 Scroll.VerticalViewSize=50.00 Scroll.VerticallyScrollable=true
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/scrollable-textarea-expected-uia-win.txt b/content/test/data/accessibility/html/scrollable-textarea-expected-uia-win.txt
index a4b795a7..b2dc4fd 100644
--- a/content/test/data/accessibility/html/scrollable-textarea-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/scrollable-textarea-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group IsControlElement=false
-++++textbox Value.Value='little'
-++++textbox Value.Value='lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text'
+Document
+++Group IsControlElement=false
+++++Edit Value.Value='little'
+++++Edit Value.Value='lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/section-expected-uia-win.txt b/content/test/data/accessibility/html/section-expected-uia-win.txt
index b1e3ebe..a15a2b7 100644
--- a/content/test/data/accessibility/html/section-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/section-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group ControlType='UIA_GroupControlTypeId'
-++++description Name='This is a section element.'
-++region ControlType='UIA_GroupControlTypeId' LocalizedControlType='section' Name='section'
-++++description Name='This is a named section element.'
+Document
+++Group
+++++Text Name='This is a section element.'
+++Group LocalizedControlType='section' Name='section'
+++++Text Name='This is a named section element.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/select-expected-uia-win.txt b/content/test/data/accessibility/html/select-expected-uia-win.txt
index 5953c08..c605a56 100644
--- a/content/test/data/accessibility/html/select-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/select-expected-uia-win.txt
@@ -1,25 +1,26 @@
-document
-++group IsControlElement=false
-++++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Placeholder option'
-++++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++++listitem Name='Placeholder option' SelectionItem.IsSelected=true
-++++++++listitem Name='Option 1' SelectionItem.IsSelected=false
-++++++++listitem Name='Option 2' SelectionItem.IsSelected=false
-++++combobox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Option 2'
-++++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++++listitem Name='Option 1' SelectionItem.IsSelected=false
-++++++++listitem Name='Option 2' SelectionItem.IsSelected=true
-++++++++listitem Name='Option 3' SelectionItem.IsSelected=false
-++++combobox IsRequiredForForm=true ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Option 1'
-++++++list Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++++listitem Name='Option 1' SelectionItem.IsSelected=true
-++++++++listitem Name='Option 2' SelectionItem.IsSelected=false
-++++++++listitem Name='Option 3' SelectionItem.IsSelected=false
-++++listbox Selection.CanSelectMultiple=true Selection.IsSelectionRequired=false
-++++++option Name='Option 1' SelectionItem.IsSelected=false
-++++++option Name='Option 2' SelectionItem.IsSelected=false
-++++++option Name='Option 3' SelectionItem.IsSelected=false
-++++listbox Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++option Name='Option 1' SelectionItem.IsSelected=false
-++++++option Name='Option 2' SelectionItem.IsSelected=false
-++++++option Name='Option 3' SelectionItem.IsSelected=false
+Document
+++Group IsControlElement=false
+++++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Placeholder option'
+++++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++++ListItem Name='Placeholder option' SelectionItem.IsSelected=true
+++++++++ListItem Name='Option 1' SelectionItem.IsSelected=false
+++++++++ListItem Name='Option 2' SelectionItem.IsSelected=false
+++++ComboBox ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Option 2'
+++++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++++ListItem Name='Option 1' SelectionItem.IsSelected=false
+++++++++ListItem Name='Option 2' SelectionItem.IsSelected=true
+++++++++ListItem Name='Option 3' SelectionItem.IsSelected=false
+++++ComboBox IsRequiredForForm=true ExpandCollapse.ExpandCollapseState='Collapsed' Value.Value='Option 1'
+++++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++++ListItem Name='Option 1' SelectionItem.IsSelected=true
+++++++++ListItem Name='Option 2' SelectionItem.IsSelected=false
+++++++++ListItem Name='Option 3' SelectionItem.IsSelected=false
+++++List Selection.CanSelectMultiple=true Selection.IsSelectionRequired=false
+++++++ListItem Name='Option 1' SelectionItem.IsSelected=false
+++++++ListItem Name='Option 2' SelectionItem.IsSelected=false
+++++++ListItem Name='Option 3' SelectionItem.IsSelected=false
+++++List Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++ListItem Name='Option 1' SelectionItem.IsSelected=false
+++++++ListItem Name='Option 2' SelectionItem.IsSelected=false
+++++++ListItem Name='Option 3' SelectionItem.IsSelected=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/selection-container-expected-uia-win.txt b/content/test/data/accessibility/html/selection-container-expected-uia-win.txt
index f64d1388..f8a2d6db 100644
--- a/content/test/data/accessibility/html/selection-container-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/selection-container-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document
-++group IsControlElement=false
-++++listbox Name='selection_list' Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
-++++++group Name='Enabled'
-++++++++description Name='Enabled' IsControlElement=false
-++++++option Name='One' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
-++++++option Name='Two' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
-++++++option Name='Three' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
-++++++option Name='Four' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
+Document
+++Group IsControlElement=false
+++++List Name='selection_list' Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false
+++++++Group Name='Enabled'
+++++++++Text Name='Enabled' IsControlElement=false
+++++++ListItem Name='One' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
+++++++ListItem Name='Two' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
+++++++ListItem Name='Three' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
+++++++ListItem Name='Four' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='selection_list'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/span-expected-uia-win.txt b/content/test/data/accessibility/html/span-expected-uia-win.txt
index 57754e1..2815441 100644
--- a/content/test/data/accessibility/html/span-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/span-expected-uia-win.txt
@@ -1,70 +1,71 @@
-document
-++group IsControlElement=false
-++++description Name='This'
-++++description Name=' '
-++++description Name='paragraph has '
-++++description Name='text'
-++++description Name=' '
-++++description Name='in'
-++++description Name=' '
-++++description Name='spans'
-++++description Name='.'
-++group IsControlElement=false
-++++description Name='E1. Eat'
-++++description Name=' '
-++++link Name='space'
-++++++description Name='space' IsControlElement=false
-++group IsControlElement=false
-++++description Name='E2. Eat'
-++++description Name=' '
-++++link Name='space'
-++++++description Name='space' IsControlElement=false
-++group IsControlElement=false
-++++description Name='E3. Eat'
-++++description Name=' '
-++++link Name='space'
-++++++description Name='space' IsControlElement=false
-++group IsControlElement=false
-++++link Name='E4. Eat'
-++++++description Name='E4. Eat' IsControlElement=false
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++link Name='E5. Eat'
-++++++description Name='E5. Eat' IsControlElement=false
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++link Name='E6. Eat'
-++++++description Name='E6. Eat' IsControlElement=false
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K1. Keep'
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K2. Keep'
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K3. Keep'
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K4. Keep '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K5. Keep'
-++++description Name=' '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K6. Keep '
-++++description Name='space'
-++group IsControlElement=false
-++++description Name='K7. Keep'
-++++description Name=' space'
-++group IsControlElement=false
-++++description Name='K8. Keep'
-++++description Name=' '
-++++description Name='space'
+Document
+++Group IsControlElement=false
+++++Text Name='This'
+++++Text Name=' '
+++++Text Name='paragraph has '
+++++Text Name='text'
+++++Text Name=' '
+++++Text Name='in'
+++++Text Name=' '
+++++Text Name='spans'
+++++Text Name='.'
+++Group IsControlElement=false
+++++Text Name='E1. Eat'
+++++Text Name=' '
+++++Hyperlink Name='space'
+++++++Text Name='space' IsControlElement=false
+++Group IsControlElement=false
+++++Text Name='E2. Eat'
+++++Text Name=' '
+++++Hyperlink Name='space'
+++++++Text Name='space' IsControlElement=false
+++Group IsControlElement=false
+++++Text Name='E3. Eat'
+++++Text Name=' '
+++++Hyperlink Name='space'
+++++++Text Name='space' IsControlElement=false
+++Group IsControlElement=false
+++++Hyperlink Name='E4. Eat'
+++++++Text Name='E4. Eat' IsControlElement=false
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Hyperlink Name='E5. Eat'
+++++++Text Name='E5. Eat' IsControlElement=false
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Hyperlink Name='E6. Eat'
+++++++Text Name='E6. Eat' IsControlElement=false
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K1. Keep'
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K2. Keep'
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K3. Keep'
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K4. Keep '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K5. Keep'
+++++Text Name=' '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K6. Keep '
+++++Text Name='space'
+++Group IsControlElement=false
+++++Text Name='K7. Keep'
+++++Text Name=' space'
+++Group IsControlElement=false
+++++Text Name='K8. Keep'
+++++Text Name=' '
+++++Text Name='space'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/sub-expected-uia-win.txt b/content/test/data/accessibility/html/sub-expected-uia-win.txt
index f72048a..13d3317 100644
--- a/content/test/data/accessibility/html/sub-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/sub-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='This text contains '
-++++description Name='subscript'
-++++description Name=' text.'
+Document
+++Group IsControlElement=false
+++++Text Name='This text contains '
+++++Text Name='subscript'
+++++Text Name=' text.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/summary-expected-uia-win.txt b/content/test/data/accessibility/html/summary-expected-uia-win.txt
index 05860971..c8b1315c 100644
--- a/content/test/data/accessibility/html/summary-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/summary-expected-uia-win.txt
@@ -1,4 +1,5 @@
-document
-++group
-++++button Name='details tag' ExpandCollapse.ExpandCollapseState='Collapsed'
-++++++description Name='details tag'
+Document
+++Group
+++++Button Name='details tag' ExpandCollapse.ExpandCollapseState='Collapsed'
+++++++Text Name='details tag'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/sup-expected-uia-win.txt b/content/test/data/accessibility/html/sup-expected-uia-win.txt
index 8c24b2a..b11f90f 100644
--- a/content/test/data/accessibility/html/sup-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/sup-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='This text contains'
-++++description Name='superscript'
-++++description Name='text.'
+Document
+++Group IsControlElement=false
+++++Text Name='This text contains'
+++++Text Name='superscript'
+++++Text Name='text.'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/svg-expected-uia-win.txt b/content/test/data/accessibility/html/svg-expected-uia-win.txt
index 1ce2090..08454be 100644
--- a/content/test/data/accessibility/html/svg-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/svg-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++img Name='svg' HelpText='SVG Title Tag'
-++++++group IsControlElement=false
-++++++++description Name='Test'
+Document
+++Group IsControlElement=false
+++++Image Name='svg' HelpText='SVG Title Tag'
+++++++Group IsControlElement=false
+++++++++Text Name='Test'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/table-focusable-sections-expected-uia-win.txt b/content/test/data/accessibility/html/table-focusable-sections-expected-uia-win.txt
index 593cffa..ca8790ef 100644
--- a/content/test/data/accessibility/html/table-focusable-sections-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/table-focusable-sections-expected-uia-win.txt
@@ -1,25 +1,26 @@
-document Name='Table example - focusable thead, tbody, tfoot'
-++grid Grid.ColumnCount=2 Grid.RowCount=4 Table.RowOrColumnMajor='RowMajor'
-++++rowgroup
-++++++row IsControlElement=false
-++++++++columnheader Name='Sum' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++++description Name='Sum' IsControlElement=false
-++++++++columnheader Name='Subtraction' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++++description Name='Subtraction' IsControlElement=false
-++++rowgroup
-++++++row IsControlElement=false
-++++++++gridcell Name='10' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++++description Name='10' IsControlElement=false
-++++++++gridcell Name='7' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++++description Name='7' IsControlElement=false
-++++++row IsControlElement=false
-++++++++gridcell Name='2' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
-++++++++++description Name='2' IsControlElement=false
-++++++++gridcell Name='4' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
-++++++++++description Name='4' IsControlElement=false
-++++rowgroup
-++++++row IsControlElement=false
-++++++++gridcell Name='12' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=3 GridItem.RowSpan=1
-++++++++++description Name='12' IsControlElement=false
-++++++++gridcell Name='3' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=3 GridItem.RowSpan=1
-++++++++++description Name='3' IsControlElement=false
+Document Name='Table example - focusable thead, tbody, tfoot'
+++Table Grid.ColumnCount=2 Grid.RowCount=4 Table.RowOrColumnMajor='RowMajor'
+++++Group
+++++++DataItem IsControlElement=false
+++++++++DataItem Name='Sum' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++++Text Name='Sum' IsControlElement=false
+++++++++DataItem Name='Subtraction' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++++Text Name='Subtraction' IsControlElement=false
+++++Group
+++++++DataItem IsControlElement=false
+++++++++DataItem Name='10' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++++Text Name='10' IsControlElement=false
+++++++++DataItem Name='7' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++++Text Name='7' IsControlElement=false
+++++++DataItem IsControlElement=false
+++++++++DataItem Name='2' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
+++++++++++Text Name='2' IsControlElement=false
+++++++++DataItem Name='4' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
+++++++++++Text Name='4' IsControlElement=false
+++++Group
+++++++DataItem IsControlElement=false
+++++++++DataItem Name='12' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=3 GridItem.RowSpan=1
+++++++++++Text Name='12' IsControlElement=false
+++++++++DataItem Name='3' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=3 GridItem.RowSpan=1
+++++++++++Text Name='3' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/table-layout-expected-uia-win.txt b/content/test/data/accessibility/html/table-layout-expected-uia-win.txt
index 84a6b1cc..0a8c4b5 100644
--- a/content/test/data/accessibility/html/table-layout-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/table-layout-expected-uia-win.txt
@@ -1,23 +1,24 @@
-document Name='Table example #2'
-++grid Grid.ColumnCount=3 Grid.RowCount=3
-++++row IsControlElement=false
-++++++gridcell Name='1' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='1' IsControlElement=false
-++++++gridcell Name='2' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='2' IsControlElement=false
-++++++gridcell Name='3' GridItem.Column=2 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='3' IsControlElement=false
-++++row IsControlElement=false
-++++++gridcell Name='4' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='4' IsControlElement=false
-++++++gridcell Name='5' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='5' IsControlElement=false
-++++++gridcell Name='6' GridItem.Column=2 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='6' IsControlElement=false
-++++row IsControlElement=false
-++++++gridcell Name='7' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
-++++++++description Name='7' IsControlElement=false
-++++++gridcell Name='8' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
-++++++++description Name='8' IsControlElement=false
-++++++gridcell Name='9' GridItem.Column=2 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
-++++++++description Name='9' IsControlElement=false
+Document Name='Table example #2'
+++Table Grid.ColumnCount=3 Grid.RowCount=3
+++++DataItem IsControlElement=false
+++++++DataItem Name='1' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='1' IsControlElement=false
+++++++DataItem Name='2' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='2' IsControlElement=false
+++++++DataItem Name='3' GridItem.Column=2 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='3' IsControlElement=false
+++++DataItem IsControlElement=false
+++++++DataItem Name='4' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='4' IsControlElement=false
+++++++DataItem Name='5' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='5' IsControlElement=false
+++++++DataItem Name='6' GridItem.Column=2 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='6' IsControlElement=false
+++++DataItem IsControlElement=false
+++++++DataItem Name='7' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
+++++++++Text Name='7' IsControlElement=false
+++++++DataItem Name='8' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
+++++++++Text Name='8' IsControlElement=false
+++++++DataItem Name='9' GridItem.Column=2 GridItem.ColumnSpan=1 GridItem.Row=2 GridItem.RowSpan=1
+++++++++Text Name='9' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/table-presentation-expected-uia-win.txt b/content/test/data/accessibility/html/table-presentation-expected-uia-win.txt
index c4764267..cbb3a621 100644
--- a/content/test/data/accessibility/html/table-presentation-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/table-presentation-expected-uia-win.txt
@@ -1,9 +1,10 @@
-document Name='Table with role=presentation'
-++group IsControlElement=false
-++++description Name='1'
-++group IsControlElement=false
-++++description Name='2'
-++group IsControlElement=false
-++++description Name='4'
-++group IsControlElement=false
-++++description Name='5'
+Document Name='Table with role=presentation'
+++Group IsControlElement=false
+++++Text Name='1'
+++Group IsControlElement=false
+++++Text Name='2'
+++Group IsControlElement=false
+++++Text Name='4'
+++Group IsControlElement=false
+++++Text Name='5'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/table-th-colheader-expected-uia-win.txt b/content/test/data/accessibility/html/table-th-colheader-expected-uia-win.txt
index 680d8bf5f4..53e879b 100644
--- a/content/test/data/accessibility/html/table-th-colheader-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/table-th-colheader-expected-uia-win.txt
@@ -1,12 +1,13 @@
-document
-++grid Grid.ColumnCount=2 Grid.RowCount=2 Table.RowOrColumnMajor='RowMajor'
-++++row IsControlElement=false
-++++++columnheader Name='Firstname' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='Firstname' IsControlElement=false
-++++++columnheader Name='Lastname' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='Lastname' IsControlElement=false
-++++row IsControlElement=false
-++++++gridcell Name='Jill' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='Jill' IsControlElement=false
-++++++gridcell Name='Smith' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='Smith' IsControlElement=false
+Document
+++Table Grid.ColumnCount=2 Grid.RowCount=2 Table.RowOrColumnMajor='RowMajor'
+++++DataItem IsControlElement=false
+++++++DataItem Name='Firstname' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='Firstname' IsControlElement=false
+++++++DataItem Name='Lastname' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='Lastname' IsControlElement=false
+++++DataItem IsControlElement=false
+++++++DataItem Name='Jill' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='Jill' IsControlElement=false
+++++++DataItem Name='Smith' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='Smith' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/table-th-rowheader-expected-uia-win.txt b/content/test/data/accessibility/html/table-th-rowheader-expected-uia-win.txt
index d0b908d8..63e08936 100644
--- a/content/test/data/accessibility/html/table-th-rowheader-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/table-th-rowheader-expected-uia-win.txt
@@ -1,12 +1,13 @@
-document Name='Table example - th rowheader'
-++grid Grid.ColumnCount=2 Grid.RowCount=2 Table.RowOrColumnMajor='RowMajor'
-++++row IsControlElement=false
-++++++rowheader Name='Firstname' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='Firstname' IsControlElement=false
-++++++gridcell Name='Jill' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
-++++++++description Name='Jill' IsControlElement=false
-++++row IsControlElement=false
-++++++rowheader Name='Lastname' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='Lastname' IsControlElement=false
-++++++gridcell Name='Smith' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
-++++++++description Name='Smith' IsControlElement=false
+Document Name='Table example - th rowheader'
+++Table Grid.ColumnCount=2 Grid.RowCount=2 Table.RowOrColumnMajor='RowMajor'
+++++DataItem IsControlElement=false
+++++++DataItem Name='Firstname' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='Firstname' IsControlElement=false
+++++++DataItem Name='Jill' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1
+++++++++Text Name='Jill' IsControlElement=false
+++++DataItem IsControlElement=false
+++++++DataItem Name='Lastname' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='Lastname' IsControlElement=false
+++++++DataItem Name='Smith' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=1 GridItem.RowSpan=1
+++++++++Text Name='Smith' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/textarea-expected-uia-win.txt b/content/test/data/accessibility/html/textarea-expected-uia-win.txt
index d8b1205..8375af8 100644
--- a/content/test/data/accessibility/html/textarea-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/textarea-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox Value.Value='The <newline>textarea tag  defines a multi-line text input control.<newline>'
+Document
+++Group IsControlElement=false
+++++Edit Value.Value='The <newline>textarea tag  defines a multi-line text input control.<newline>'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/textarea-read-only-expected-uia-win.txt b/content/test/data/accessibility/html/textarea-read-only-expected-uia-win.txt
index 9c159ed..a8b62c0 100644
--- a/content/test/data/accessibility/html/textarea-read-only-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/textarea-read-only-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox Value.Value='The textarea tag defines a multi-line text input control.<newline>'
+Document
+++Group IsControlElement=false
+++++Edit Value.Value='The textarea tag defines a multi-line text input control.<newline>'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/textarea-with-selection-expected-uia-win.txt b/content/test/data/accessibility/html/textarea-with-selection-expected-uia-win.txt
index 9c159ed..a8b62c0 100644
--- a/content/test/data/accessibility/html/textarea-with-selection-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/textarea-with-selection-expected-uia-win.txt
@@ -1,3 +1,4 @@
-document
-++group IsControlElement=false
-++++textbox Value.Value='The textarea tag defines a multi-line text input control.<newline>'
+Document
+++Group IsControlElement=false
+++++Edit Value.Value='The textarea tag defines a multi-line text input control.<newline>'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/time-expected-uia-win.txt b/content/test/data/accessibility/html/time-expected-uia-win.txt
index 8766d42..f00991d6 100644
--- a/content/test/data/accessibility/html/time-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/time-expected-uia-win.txt
@@ -1,7 +1,8 @@
-document
-++group IsControlElement=false
-++++time LocalizedControlType='time'
-++++++description Name='10:00'
-++++description Name=' '
-++++time LocalizedControlType='time'
-++++++description Name='Valentines day'
+Document
+++Group IsControlElement=false
+++++Text LocalizedControlType='time'
+++++++Text Name='10:00'
+++++Text Name=' '
+++++Text LocalizedControlType='time'
+++++++Text Name='Valentines day'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/title-expected-uia-win.txt b/content/test/data/accessibility/html/title-expected-uia-win.txt
index 520e0c2..8b05cda4 100644
--- a/content/test/data/accessibility/html/title-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/title-expected-uia-win.txt
@@ -1 +1,2 @@
-document Name='Title of the document'
+Document Name='Title of the document'
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/ul-expected-uia-win.txt b/content/test/data/accessibility/html/ul-expected-uia-win.txt
index 76d345e..4c07ffe2 100644
--- a/content/test/data/accessibility/html/ul-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/ul-expected-uia-win.txt
@@ -1,14 +1,15 @@
-document
-++list
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Item 1' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Item 2' IsControlElement=false
-++++listitem
-++++++group
-++++++++description Name='• ' IsControlElement=false
-++++++description Name='Item 3' IsControlElement=false
+Document
+++List
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Item 1' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Item 2' IsControlElement=false
+++++ListItem
+++++++Group
+++++++++Text Name='• ' IsControlElement=false
+++++++Text Name='Item 3' IsControlElement=false
+<-- End-of-file -->
diff --git a/content/test/data/accessibility/html/wbr-expected-uia-win.txt b/content/test/data/accessibility/html/wbr-expected-uia-win.txt
index 2056c64..cec2de9 100644
--- a/content/test/data/accessibility/html/wbr-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/wbr-expected-uia-win.txt
@@ -1,5 +1,6 @@
-document
-++group IsControlElement=false
-++++description Name='Supercali'
-++++description Name='fragilistic'
-++++description Name='expialidocious'
+Document
+++Group IsControlElement=false
+++++Text Name='Supercali'
+++++Text Name='fragilistic'
+++++Text Name='expialidocious'
+<-- End-of-file -->
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 5e725ea..880e4dd 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1505,6 +1505,7 @@
   AUTOFILLASSISTANTPRIVATE_PROVIDEUSERDATA = 1442,
   PASSWORDSPRIVATE_ISOPTEDINFORACCOUNTSTORAGE = 1443,
   AUTOTESTPRIVATE_PINSHELFICON = 1444,
+  AUTOTESTPRIVATE_WAITFOROVERVIEWSTATE = 1445,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 840fd84a..f6e3c744 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -878,11 +878,15 @@
 }
 
 gl::GLContext* RasterDecoderImpl::GetGLContext() {
-  return shared_context_state_->context();
+  return shared_context_state_->GrContextIsGL()
+             ? shared_context_state_->context()
+             : nullptr;
 }
 
 gl::GLSurface* RasterDecoderImpl::GetGLSurface() {
-  return shared_context_state_->surface();
+  return shared_context_state_->GrContextIsGL()
+             ? shared_context_state_->surface()
+             : nullptr;
 }
 
 Capabilities RasterDecoderImpl::GetCapabilities() {
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index 4350dfc..2f3fda70 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -145,7 +145,7 @@
     SharedImageManager* shared_image_manager,
     GpuMemoryBufferFactory* gpu_memory_buffer_factory,
     const GpuFeatureInfo& gpu_feature_info,
-    GpuProcessActivityFlags* const activity_flags,
+    GpuProcessActivityFlags activity_flags,
     scoped_refptr<gl::GLSurface> default_offscreen_surface,
     ImageDecodeAcceleratorWorker* image_decode_accelerator_worker,
     viz::VulkanContextProvider* vulkan_context_provider,
@@ -170,7 +170,7 @@
       discardable_manager_(gpu_preferences_),
       passthrough_discardable_manager_(gpu_preferences_),
       image_decode_accelerator_worker_(image_decode_accelerator_worker),
-      activity_flags_(activity_flags),
+      activity_flags_(std::move(activity_flags)),
       memory_pressure_listener_(
           base::BindRepeating(&GpuChannelManager::HandleMemoryPressure,
                               base::Unretained(this))),
@@ -199,10 +199,7 @@
   gpu_channels.clear();
 
   if (default_offscreen_surface_.get()) {
-    // GpuChannelManager may be temporarily destructed when chrome is
-    // backgrounded on low end device, so don't call destroy.
-    if (default_offscreen_surface_->HasOneRef())
-      default_offscreen_surface_->Destroy();
+    default_offscreen_surface_->Destroy();
     default_offscreen_surface_ = nullptr;
   }
 
@@ -234,7 +231,7 @@
       program_cache_.reset(new gles2::MemoryProgramCache(
           gpu_preferences_.gpu_program_cache_size, disable_disk_cache,
           workarounds.disable_program_caching_for_transform_feedback,
-          activity_flags_));
+          &activity_flags_));
     }
   }
   return program_cache_.get();
@@ -395,7 +392,9 @@
     stub = channel->GetOneStub();
     if (stub) {
       DCHECK(stub->decoder_context());
-      break;
+      // With Vulkan, Dawn, etc, RasterDecoders don't use GL.
+      if (stub->decoder_context()->GetGLContext())
+        break;
     }
   }
   if (!stub || !stub->decoder_context()->MakeCurrent())
@@ -567,7 +566,7 @@
     }
     shared_context_state_->InitializeGrContext(
         gpu_preferences_, gpu_driver_bug_workarounds_, gr_shader_cache(),
-        activity_flags_, watchdog_);
+        &activity_flags_, watchdog_);
   }
 
   gr_cache_controller_.emplace(shared_context_state_.get(), task_runner_);
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h
index 5c145de..9a4ab313 100644
--- a/gpu/ipc/service/gpu_channel_manager.h
+++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -79,7 +79,7 @@
       SharedImageManager* shared_image_manager,
       GpuMemoryBufferFactory* gpu_memory_buffer_factory,
       const GpuFeatureInfo& gpu_feature_info,
-      GpuProcessActivityFlags* const activity_flags,
+      GpuProcessActivityFlags activity_flags,
       scoped_refptr<gl::GLSurface> default_offscreen_surface,
       ImageDecodeAcceleratorWorker* image_decode_accelerator_worker,
       viz::VulkanContextProvider* vulkan_context_provider = nullptr,
@@ -270,7 +270,7 @@
 
   // Flags which indicate GPU process activity. Read by the browser process
   // on GPU process crash.
-  GpuProcessActivityFlags* const activity_flags_;
+  GpuProcessActivityFlags activity_flags_;
 
   base::MemoryPressureListener memory_pressure_listener_;
 
diff --git a/gpu/ipc/service/gpu_channel_test_common.cc b/gpu/ipc/service/gpu_channel_test_common.cc
index 55b6aea..4deb51f 100644
--- a/gpu/ipc/service/gpu_channel_test_common.cc
+++ b/gpu/ipc/service/gpu_channel_test_common.cc
@@ -90,7 +90,7 @@
       task_runner_.get(), io_task_runner_.get(), scheduler_.get(),
       sync_point_manager_.get(), shared_image_manager_.get(),
       nullptr, /* gpu_memory_buffer_factory */
-      std::move(feature_info), &activity_flags_,
+      std::move(feature_info), GpuProcessActivityFlags(),
       gl::init::CreateOffscreenGLSurface(gfx::Size()),
       nullptr /* image_decode_accelerator_worker */));
 }
diff --git a/gpu/ipc/service/gpu_channel_test_common.h b/gpu/ipc/service/gpu_channel_test_common.h
index b0b60d3c..1a15276 100644
--- a/gpu/ipc/service/gpu_channel_test_common.h
+++ b/gpu/ipc/service/gpu_channel_test_common.h
@@ -10,7 +10,6 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/unsafe_shared_memory_region.h"
-#include "gpu/command_buffer/common/activity_flags.h"
 #include "ipc/ipc_test_sink.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -65,7 +64,6 @@
   std::unique_ptr<Scheduler> scheduler_;
   std::unique_ptr<TestGpuChannelManagerDelegate> channel_manager_delegate_;
   std::unique_ptr<GpuChannelManager> channel_manager_;
-  GpuProcessActivityFlags activity_flags_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuChannelTestCommon);
 };
diff --git a/infra/config/generated/tricium-prod.cfg b/infra/config/generated/tricium-prod.cfg
index 9e24eb8..4529991 100644
--- a/infra/config/generated/tricium-prod.cfg
+++ b/infra/config/generated/tricium-prod.cfg
@@ -70,19 +70,6 @@
 }
 
 selections {
-  function: "Cpplint"
-  platform: UBUNTU
-  configs {
-    name: "filter"
-    value: "-,+readability/todo,+readability/check,+readability/fn_size,+build/header_guard,+build/include_order"
-  }
-  configs {
-    name: "verbose"
-    value: "4"
-  }
-}
-
-selections {
   function: "GitFileIsolator"
   platform: UBUNTU
 }
diff --git a/infra/config/tricium-prod.cfg b/infra/config/tricium-prod.cfg
index 9e24eb8..4529991 100644
--- a/infra/config/tricium-prod.cfg
+++ b/infra/config/tricium-prod.cfg
@@ -70,19 +70,6 @@
 }
 
 selections {
-  function: "Cpplint"
-  platform: UBUNTU
-  configs {
-    name: "filter"
-    value: "-,+readability/todo,+readability/check,+readability/fn_size,+build/header_guard,+build/include_order"
-  }
-  configs {
-    name: "verbose"
-    value: "4"
-  }
-}
-
-selections {
   function: "GitFileIsolator"
   platform: UBUNTU
 }
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index 4b6b749..22b30a542 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -160,6 +160,7 @@
     case CONNECTION_INFO_QUIC_Q099:
     case CONNECTION_INFO_QUIC_T099:
     case CONNECTION_INFO_QUIC_999:
+    case CONNECTION_INFO_QUIC_DRAFT_25:
       return CONNECTION_INFO_COARSE_QUIC;
 
     case CONNECTION_INFO_UNKNOWN:
@@ -493,6 +494,7 @@
     case CONNECTION_INFO_QUIC_Q099:
     case CONNECTION_INFO_QUIC_T099:
     case CONNECTION_INFO_QUIC_999:
+    case CONNECTION_INFO_QUIC_DRAFT_25:
       return true;
     case NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
@@ -571,6 +573,8 @@
       return "h3-T050";
     case CONNECTION_INFO_QUIC_Q099:
       return "h3-Q099";
+    case CONNECTION_INFO_QUIC_DRAFT_25:
+      return "h3-25";
     case CONNECTION_INFO_QUIC_T099:
       return quic::AlpnForVersion(quic::ParsedQuicVersion(
           quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_99));
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index c166b5c..f6bdf50 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -71,6 +71,7 @@
     CONNECTION_INFO_QUIC_T049 = 32,
     CONNECTION_INFO_QUIC_T050 = 33,
     CONNECTION_INFO_QUIC_T099 = 34,
+    CONNECTION_INFO_QUIC_DRAFT_25 = 35,
     NUM_OF_CONNECTION_INFOS,
   };
 
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 23611ca7..1cc23a55 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -3524,16 +3524,21 @@
       base::MakeRefCounted<HttpResponseHeaders>(""));
   headers->AddHeader(
       "alt-svc: "
-      "h3-25=\":443\",h3-Q050=\":443\",h3-Q049=\":443\",h3-Q048=\":443\",h3-"
-      "Q047=\":443\",h3-"
-      "Q043=\":443\",h3-"
-      "Q039=\":443\"");
+      "h3-26=\":443\","
+      "h3-25=\":443\","
+      "h3-Q050=\":443\","
+      "h3-Q049=\":443\","
+      "h3-Q048=\":443\","
+      "h3-Q047=\":443\","
+      "h3-Q043=\":443\","
+      "h3-Q039=\":443\"");
 
   session_->http_stream_factory()->ProcessAlternativeServices(
       session_.get(), network_isolation_key, headers.get(), origin);
 
   quic::ParsedQuicVersionVector versions = {
       {quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_99},
+      {quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_IETF_DRAFT_25},
       {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_50},
       {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_49},
       {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_48},
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index d1a9058f..f45cdd10 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -94388,6 +94388,2014 @@
     { "name": "znwvw.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zumba.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zwangerschapspecialist.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1-weightloss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1003365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100eeee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100ffff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100gggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100hhhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100kkkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100pppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100rrrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100tttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100yyyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100zzzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ae.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110al.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110au.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110bu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110bv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110cb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110cl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ef.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110eh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ej.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110en.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110es.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110et.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110fn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110fr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110gf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110gh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110gs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110hq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110jf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110jt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ju.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110jx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110kh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110kn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110kp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110lh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110lj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110na.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ne.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110nf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110nl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110nr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110nx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110nz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110pe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110qa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110qc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110qs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110qu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110rd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110rl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110sk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110uh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ut.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110wc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110wd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110we.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110wf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110wq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110wy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110xn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110xp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110xz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110yj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110yl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110yn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110yt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110yu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110ze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110zg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "110zw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1112365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1116365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1119365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11aaee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11aagg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11aajj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11aaqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11aass.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11aazz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11bbzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11cchh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11cckk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11cctt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ccyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11cczz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ddzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eebb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eecc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eedd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eeff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eegg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eehh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eejj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eepp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eeqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eess.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eett.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eexx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eeyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11eezz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11fftt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ffzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ggzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11hhzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11jjzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11kkee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11kkff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11kkss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11kkyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11pphh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11pptt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ppzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11qqzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rryy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11rrzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ssff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11sshh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ssjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11sskk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11sspp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ssqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ssrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11sstt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11sszz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11tthh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11ttzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yybb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yycc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yydd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yyee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yygg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yyjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yykk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yypp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yyqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yyrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yytt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yyxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11yyzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zztt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "11zzyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "12ca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "136book.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158be.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158bh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158bi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158bq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158fb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158gs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158ia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158in.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158iw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158nb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158yt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158yu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158yv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158za.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158zh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162be.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162bf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162bj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162ca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162ce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162ch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162cy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162dc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162dg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162ea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162ee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162ff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162jj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "162rt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "16te.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1869365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1876365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1981365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200ffff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200gggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200hhhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200kkkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200llll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200mmmm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200oooo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200pppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200rrrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200wwww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200xxxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200yyyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "200zzzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "211hh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "21stcenturybuildingcompany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "220220.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "222yn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aaee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aagg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aahh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aaii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aajj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aarr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aaxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22aayy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22atat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22bbgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22bbhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22bbii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22bbjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22bbtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22bbyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ccaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ccbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ccee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ccpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ccxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22cncn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ddrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22eebb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22eedd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22eeff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22eegg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22eekk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22eess.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ffcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ffgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ffpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ffxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ggaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ggdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22gugu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22haha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22haose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22hehe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22hhcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22hhii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22hhqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22iigg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22iirr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22iiyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22jjbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22jjdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22jjyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22kkdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22kkpp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22kkss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22kkyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22momo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ppdd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ppgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ppss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22pptt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22qqbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22qqgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22qqii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22qqjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22qqrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22qqtt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22rere.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22rree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22rrff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22rrss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ruru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ssbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ssjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22sskk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22sstt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22tete.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ttgg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22ttkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22xxhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22xxjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22xxyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yybb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yydd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yyii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yyjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yykk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yypp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yyqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yyrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yyss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yytt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22yyxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2337365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "24848966.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "24848988.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "24848h.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256ab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256ac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256be.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256br.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256bx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256ge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256hh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256hk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256pb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256pf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256rr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "256tq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "262569.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "269196.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26bbc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26ce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26ck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26ddc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26gt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26he.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26ja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26na.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26nc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26nd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26pa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26pe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26pg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26pn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26rd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26sn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26sr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26ssb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26uuu.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26xe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "26yk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "299zzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2nimpresores.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300ffff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300gggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300hhhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300kkkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300llll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300mmmm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300oooo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300rrrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "300xxxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "323kkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33acac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33ao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33eh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33ej.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33iz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33knkn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33kpkp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33vu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33zaza.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33zv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "33zxzx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ae.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34bk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34da.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34fc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34fy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34gn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34gr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34gv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34hc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34he.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34if.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34il.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34iu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34iv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34je.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34jw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34kr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34lz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34ni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34nw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34oa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34oh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34om.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34oy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34pl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34pv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34py.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34qa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34qf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34qo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34qx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34sh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34sk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34uf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34va.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34vz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34wv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34xc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34xt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34xu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34yt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34zi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "34zq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3558365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3559365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35dr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35ga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35if.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35jq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35ud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35ue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35uh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35uj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "35vn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3658200.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3659868.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3659869.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365zg.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369az.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369be.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369bk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369bn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369bp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369bq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369br.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369bu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369bw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369cd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369cr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369cu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369df.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369dk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369dp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369dr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369eh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369em.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369eq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ez.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369fj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369fm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369fn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369fy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369gh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369gp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369mb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369mr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369nk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369pb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369qb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369rr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369tw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369ve.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "369wt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36ga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36gx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36ja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36jn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36kn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36ky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36pd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36pg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36xk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36xn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36yf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36yj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "372bbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "377zzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "383aaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4003365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4004365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4005365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400eeee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400gggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400llll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400nnnn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400pppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400tttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "400yyyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "440cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ae.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ah.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46aj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46az.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46br.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46bx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46cg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46cu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46da.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46db.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46df.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46dk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46dn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46dr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46dx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46eb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ef.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46eg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46eh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ej.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46eq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46es.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46et.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ez.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46fx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46gz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46hc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46he.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46hf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46hi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46hl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46if.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ig.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ij.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46iq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ir.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46iy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46iz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46jc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46jd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46jr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46jx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46kz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46lf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46lj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46lk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46lq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46lt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46na.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46nk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46nr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46nu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46pg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46pj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46pn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46pq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46pz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ql.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46qt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46rz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46sd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46sg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46sp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46sr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46sx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46td.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46te.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46tf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46tj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46tn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46tr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46tz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ua.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46uk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46uq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ut.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ux.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46uz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46xa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46xe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46xj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46yz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46zt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47af.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47an.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47dp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47fd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47fl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47gq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47gr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47hc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47hf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47hv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47iz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47jc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47kl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47lo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47nf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47nh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47nt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ph.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47qe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47rd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47rv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47tf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47tw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47uy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47vg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47vk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47vy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47vz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47wv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47xc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47xt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47yz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47za.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47ze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "47zv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500eeee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500mmmm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500nnnn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500rrrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500tttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500xxxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500yyyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "500zzzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "51kly.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "529sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "566zzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "5e.tools", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "5long88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600cao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600gao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600kkkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600llll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600mmmm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600pppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600ssss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600tttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600wwww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "600xxxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "622bbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63aj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63at.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63bg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63bh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63cb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63co.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63dt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63eb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63eh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ej.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63en.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63et.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63fq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63gu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63he.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63hq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63hv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63hx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ib.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63if.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ig.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63im.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63iq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ir.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63iv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63iw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63jg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63jl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63jr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63jw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63kd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63kl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63kn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63kv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63kz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63lb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63lc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63lo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63lr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63md.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63mf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63mj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63mq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63nc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63nd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63nk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63nl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63np.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63nx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63of.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63pd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63pl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63qb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63qz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63re.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63rh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63rj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63rk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63rn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63rz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63tf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63to.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63tx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63uf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63um.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63ut.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63uz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63vg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63vo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "63wq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365i.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365j.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365k.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365l.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365m.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365n.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365o.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365p.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365v.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365x.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365y.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "663365z.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6728365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "672bbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "673bbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700gggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700hhhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700mmmm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700nnnn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700oooo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700pppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700ssss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700tttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700wwww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700yyyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "700zzzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7111365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "727sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73af.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73aj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73az.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73dt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73eb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ef.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73eg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73eh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ei.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ej.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73en.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73eq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73es.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73eu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ew.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ez.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73fz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73gx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73hb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73hc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73hn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73hw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73if.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ig.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ih.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73iw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73iy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73je.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73jn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73kc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73kn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73kp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73lg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ln.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73nj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73nk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73nm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73np.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73nq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73nw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73nz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73pb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73pe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73pl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73px.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73qa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73qd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73qe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ql.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73qx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73rh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73rq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73rt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73si.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73sk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73te.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73tf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73tg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73tq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73tx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73uh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73ui.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73uk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73un.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73uq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73uy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73vt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73vz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73wb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73wj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73wt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73xh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73xi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73xm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73xv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73yj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73yp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73yr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73yu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73za.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "73zd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "77caca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "77zaza.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "788zzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "798sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800eeee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800hhhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800kkkk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800llll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800nnnn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800pppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800rrrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800wwww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800xxxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "800zzzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8106365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8132365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8153365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8167365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "81sese.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "81sese.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "81sese.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8230d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ag.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84aj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84al.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84an.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84aq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84at.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84az.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84be.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84bx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84cx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84df.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84dp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84dt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84eg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ei.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84et.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ew.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ez.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84fz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84gc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84gf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84gh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84gi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84gk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84gt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84hb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84he.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84hp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84hs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84hv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84hx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84if.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84im.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84jg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84jh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84jl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84jp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84jt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84kz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84lb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84lh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84nf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84nv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84nx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84pb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84pd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84pe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84pg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ph.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84pq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84qa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84qb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84qf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84qi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84qj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84qx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84rb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84rd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84rf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84rn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84rt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84sg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84sr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84sv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84td.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84tn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84tp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84tw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84tx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ua.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84xa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84xe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84xl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84xm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84xp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84yw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84za.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84ze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "84zv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8835365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "88caca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "88zaza.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "89ca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900aaaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900bbbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900cccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900dddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900eeee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900gggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900iiii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900jjjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900nnnn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900qqqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900tttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900uuuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900vvvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900wwww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900yyyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "900zzzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9111365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9132365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9137365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9528365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "96658.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "96685.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "981ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "982zzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9859365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "985ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "986ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "989ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "993ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a3sys-elodie.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aa4888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aaronmaar.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abc636.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abovethehimalaya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "accountmover.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acronym24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adam.id.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adchina.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adspu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ae86.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ae86.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ae86.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "africanewstest0.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ai2-jp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aileenwatt.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alarmcast.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "albayan.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alcohollawadvisor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexdiazdeleon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexmainz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexmainz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexmainz.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alivelimo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allerlei-havelte.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amaruddinmufid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ambicorprealestate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "andrewtaylor.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anex.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aniwatch.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "apinsa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aranym.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arcza.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arcza.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arn0.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ascar.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asngear.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atacarejovirtual.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atec.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atelier-tecna.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atelierjs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atlanticomp.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "attractiontest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "audionames.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "automekano.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "autonewsreview.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "autostramites.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b0000.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b1111.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b131000.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b2222.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b789.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b979333.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b979555.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b979666.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b979999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "badnjar.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "banajanitorialservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barberiaicon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bassment.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bbk365m.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bbk365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bbk365zz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bellapierre.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "berzkalne.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "besiktasmtsk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestsellers.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestweleenbeetje.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bethematch.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bethematchclinical.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bibisbootypalace.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bigtrucker.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bimsynergistics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "birdsnow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blanx.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blaskapellehohenpoelz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bmyjacks.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookaway.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bou.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brownandjoseph.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btdays.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buildinghopeforafrica.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "builds.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buphachat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bva.dyndns.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cabbage.software", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cadcc.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cafethevibes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "callofdutybr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "camrojud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "capila.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caroletolila.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "catsnow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ccdnederland.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cds-infra.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chaonengsou.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cheapmarina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chrismax89.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chsamuel.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cimen.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "citytourgirls.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cjwagner.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cleangroup.in.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cocoricos.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "codefaq.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "confirmit.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "connectionjapan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "convierteenabudancia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "countrymountaininn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coworkanywhere.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cqr.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crazyfoodninja.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "criptofy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptocurrencyfare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptoearnblog.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cubikus.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dabstairs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "danbs.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darci.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darkmilknyeremeny.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dastelefonbuch.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "delvinoadegas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "delycate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "derbysound.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "desarrollosmoyan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "detonic.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "devloope.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digitalcarbide.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digitalrocks.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disenowebakus.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "divienna.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dmiapis.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doetwat.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dogsnow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dondibogusky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dorwartsgarage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drsarah.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dufort.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "duinomaker.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dukeipai.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ecodepur.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ecuapaginas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edarlyn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eden.bz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edwardkong.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eggs.gold", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eiber.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elsenzhafen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "employmentlawworldview.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "empregopraontem.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eproceedings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "equinenow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "equityelevate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eremnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eromasajes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "escuelaelretamo.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etherandir.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ethereal.games", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evai.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evan.mn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ezguamal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faceyogamethod.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faithfulroad.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "famouscelebsurgery.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "farcaster.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "festrentcar.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "filarakia.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fileunemployment.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "filipdima.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "firechip.srl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "firstgradeframeofmind.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fisch-club.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fitnhot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fixvoltage.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fkbae.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flatsurfers.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "floralin.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flowdise.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnckfashion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foochia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fortressis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foxscore.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "francoise-angelini.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frederickbourget.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "funtransport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "furnitureindahjepara.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "futurologists.ltd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fysiotherapiesimons.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "g-projects.herokuapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "galaxy-chat.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "galvincdn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gatorskinsramps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "geo-industrie.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "geocostarica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "geourl.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getstat.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "giaydantuonghanhphuc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "girlsbar-navi.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glytchenergy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goldengatesports.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gouplinkit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "graphotism.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenway-moving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "growebmarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gtxcn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gumbo-millennium.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gumbo.nu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gununsesiaz.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guoliangwu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guruwebseo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ha-blog.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haberver.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hackforgood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haixingyun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hanes.house", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hardmagic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hautzentrumwien.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hersmartchoice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hidglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "highgatejoinery.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "highlandpublicschool.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "himalayanoutback.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hirmozaik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homen.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homequipment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homesidingpros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homewindowrepairpros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "houstondiabetesinstitute.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icap.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icl82.systems", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iechistore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ifsh.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ilovecomputering.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impresapulizie.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inbrand.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "indlut.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "indomebel.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "infinitybooksindia.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "injapan.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inkandtonerni.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "insideoutfuel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "investorfare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ip.dog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "irenelove.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iringtone.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "irisdesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itabi.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itajvi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itsapps.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "j51365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jackwarren.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jakartacloudhosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jamiehansonyoga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "japlin.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jdtangney.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jeeptourpocos.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jennastjohn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jenyak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jetular.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jetular.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joeainsworth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "johnblackwell.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "johnex.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joomlainfo.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jubodarpan.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jult.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaminastudios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kanalasal.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kandwliquor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kantoorboel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaya-architekten.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kd3.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keepingitheel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kesslerandsons.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kikoskia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kinderlachen.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kingsgategrease.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kirina.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitke.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kiweeagentur.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kkaramela.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "knorrnet.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kokyu-caba.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "komodo.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kylehaka.la", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kylehakala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "labsitserviss.lv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lanierlaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lechucero.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leonvermunt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "letote.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livingtohearsix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "localbiketrader.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "localemergencyplumber24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "localrvs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loja351.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "long100.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loots.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lpl-ig.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lumieredesoy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m1g.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m7rxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maddisondouch.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magliner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "majemedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mallgastronomico.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "malsignature.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mangomercado.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marica.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marketingproducts.review", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marketwingsmobile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matchday.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mathleaks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mathleaks.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mauroalejandro.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maximum-rent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meandb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mecp.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melonhub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mental-check.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mero.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meulk.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mew.build", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meyer-horn.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mnrv.trade", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mobilecraftingco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mode-musthaves.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mossipanama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mountainairandheating.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mrbighungary.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "musthavesforreal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "my77.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mygreeley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myworkoutsite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "national.co.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neosys.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neosys.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netrilo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newgle.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nextsociety.la", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nexustraducoes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ngawa-avocat-paris.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "niemandmussirgendwas.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nikelunartw.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nizozemsku.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nmb.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nn04.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nolz.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noriskit.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "notecopies.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ntgvision.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ntz.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nyx.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obzoroff.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "odxin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ourmemoriesonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "outrider.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "owmobility.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p7jl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88813.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88814.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88816.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88817.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88823.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88825.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88827.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88829.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88835.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88836.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88845.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88848.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88856.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p88867.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p888a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pablosaraiva.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "panelesyperfiles.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "papascave.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "papastratosmazi.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parki.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pascalandy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pc-reanimator.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peliculator.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petstok.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phtechcommunity.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phuket-diving-thailand.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pic.pm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "picsastock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pimentokinderboeken.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pirateproxy.uno", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pn.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "podd.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "point-to-point.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pomadgw.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "priceless-jewelry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pro100blogger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "projectvault.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "projectveritasaction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prospreads.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prox.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proxybay.uno", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pscom.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pspenvases.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ptlync.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qiyan.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qkek.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quantrix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qwantrank.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "r72w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rafue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rankankan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ravne.land", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "realitystarfacts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "recepty-s-foto.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "recuperatufigura.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redcapital.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redmejoracontinua.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "refaaygroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "regtify.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "renewablepedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rentamosandamios.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "romsp.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ronhose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ross-mitchell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rowery.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royalhosting.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rpguru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ryanrichardwalker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schoutenseo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "secure-consult.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seekalhar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seismas1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seniormanager.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "senpromotion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "setinfo.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shahurology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shansing.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "share-io.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shortcutable.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shortwave.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sigint.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "silo.nyc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simyakoleji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sloganfarm.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slu2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smb-analytics.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sostm.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sottm.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soyelectricistagdl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spantrix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sparkandpook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spotifyfreetrial.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "squarecat.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "srizer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stallionsnow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stevenson.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "straightupbrands.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "strategicpartnersmedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "studentsfirstnb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stzur.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunnynetworks.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "supplementalconditions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t-network.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8803.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8805.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8807.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8809.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8815.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8817.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8819.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t8830.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88jj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88mm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88nn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88oo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88ss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip0.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip4.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip5.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t88vip7.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tamiloburgos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tangramins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tascout.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tealojamos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "technicalhelps.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tecknologg.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "telafrictv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "terence2008.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "terrapinstationmd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "testsitefortask.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texastoadranch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texel.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tfq.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tft-cheat-sheet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thatlooksreallygood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thehimachal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "themusthaves.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "themusthaves.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theolodewijk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theparkcornwall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "therattrick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thesacreds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thetradingletter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thetrove.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thetrove.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thinkbrands.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thinktankofthree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thomas-bronniart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thorsten-schaefer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thvideo.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tjmarron.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "topdocumentaryfilms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toppsychiatristkolkata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalityservices.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradingyourownway.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "travelgirlsclub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trenta.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trevormarron.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "triplejprints.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tsk.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt0766.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt0966.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt2866.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt3699.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt3766.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt3999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt7199.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt7299.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt7399.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt8166.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt8266.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tt8366.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "umanews.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upsihologa.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "utashop.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v156.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v167.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v521.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v5658.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v7090.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v839.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valuesetters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "venture-ridge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vev.com.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vichama.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "victorique.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "visse-if.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vns6654.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vosges-tourisme.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "votegreece.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "w123.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warmteshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wb-cw.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "weinfuse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wilomark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "windeloo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wisereshape.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wmi4.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "worksindev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wwwhackeronecom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x-way.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x77ee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--6n2ao17b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--80aabn5d9h.xn--90a3ac", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--oj-uu2c9c422w3mh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xybnb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yabo68.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ygopro.in.th", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yigelangzi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ying.gift", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourartdna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yr.sa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "z2a4.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zaferaniehearing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zamor.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeglujemy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zhoujianghan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zieler.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zivver.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zlvd7.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/http2/platform/impl/http2_logging_impl.h b/net/http2/platform/impl/http2_logging_impl.h
index 4ce1f26..92f1a33 100644
--- a/net/http2/platform/impl/http2_logging_impl.h
+++ b/net/http2/platform/impl/http2_logging_impl.h
@@ -17,6 +17,7 @@
 #define HTTP2_DVLOG_IMPL(verbose_level) DVLOG(verbose_level)
 #define HTTP2_DVLOG_IF_IMPL(verbose_level, condition) \
   DVLOG_IF(verbose_level, condition)
+#define HTTP2_LOG_FIRST_N_IMPL(severity, n) HTTP2_LOG_IMPL(severity)
 
 #define HTTP2_CHROMIUM_LOG_INFO VLOG(1)
 #define HTTP2_CHROMIUM_LOG_WARNING DLOG(WARNING)
diff --git a/net/quic/platform/impl/quic_test_impl.cc b/net/quic/platform/impl/quic_test_impl.cc
index a7e57370..073817d8 100644
--- a/net/quic/platform/impl/quic_test_impl.cc
+++ b/net/quic/platform/impl/quic_test_impl.cc
@@ -31,8 +31,10 @@
 namespace quic {
 ParsedQuicVersionVector AllVersionsExcept99() {
   ParsedQuicVersionVector result;
+  // TODO(dschinazi): Remove QUIC_VERSION_IETF_DRAFT_25 from below.
   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
-    if (version.transport_version != QUIC_VERSION_99) {
+    if (version.transport_version != QUIC_VERSION_99 &&
+        version.transport_version != QUIC_VERSION_IETF_DRAFT_25) {
       result.push_back(version);
     }
   }
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index e673d4f..7591f83 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -1339,7 +1339,7 @@
   }
   if (quic::QuicUtils::IsClientInitiatedStreamId(
           connection()->transport_version(), id) ||
-      (connection()->transport_version() == quic::QUIC_VERSION_99 &&
+      (connection()->version().HasIetfQuicFrames() &&
        quic::QuicUtils::IsBidirectionalStreamId(id))) {
     LOG(WARNING) << "Received invalid push stream id " << id;
     connection()->CloseConnection(
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index 2f677c2..13ce1d6e 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -253,7 +253,7 @@
   size_t GetMaxAllowedOutgoingBidirectionalStreams() {
     quic::QuicSession* quic_session =
         dynamic_cast<quic::QuicSession*>(&*session_);
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       return quic::test::QuicSessionPeer::GetStreamIdManager(quic_session)
           ->max_open_outgoing_streams();
     }
@@ -555,7 +555,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, AsyncStreamRequest) {
   MockQuicData quic_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -608,7 +608,7 @@
                                GetNthClientInitiatedBidirectionalStreamId(0),
                                quic::QUIC_STREAM_CANCELLED, 0);
   session_->OnRstStream(rst);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     // For version99, to close the stream completely, we also must receive a
     // STOP_SENDING frame:
     quic::QuicStopSendingFrame stop_sending(
@@ -634,7 +634,7 @@
 // to read the last packet, reading that packet should not crash.
 TEST_P(QuicChromiumClientSessionTest, ReadAfterConnectionClose) {
   MockQuicData quic_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -701,7 +701,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, ClosedWithAsyncStreamRequest) {
   MockQuicData quic_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -764,7 +764,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelPendingStreamRequest) {
   MockQuicData quic_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -817,7 +817,7 @@
                                GetNthClientInitiatedBidirectionalStreamId(0),
                                quic::QUIC_STREAM_CANCELLED, 0);
   session_->OnRstStream(rst);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     // For version99, we require a STOP_SENDING as well as a RESET_STREAM to
     // fully close the stream.
     quic::QuicStopSendingFrame stop_sending(
@@ -914,13 +914,13 @@
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseWithPendingStreamRequest) {
   MockQuicData quic_data(version_);
   int packet_num = 1;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS,
                        client_maker_.MakeInitialSettingsPacket(packet_num++));
   }
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakePingPacket(packet_num++, true));
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
                                         packet_num++, true, 50,
                                         /*unidirectional=*/false));
@@ -968,7 +968,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
   MockQuicData quic_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // Initial configuration is 50 dynamic streams. Taking into account
     // the static stream (headers), expect to block on when hitting the limit
@@ -1393,7 +1393,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
   MockQuicData quic_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
                                         2, true, 50,
diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc
index 448f061..3291b9baf 100644
--- a/net/quic/quic_chromium_client_stream_test.cc
+++ b/net/quic/quic_chromium_client_stream_test.cc
@@ -260,7 +260,7 @@
   }
 
   std::string ConstructDataHeader(size_t body_len) {
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       return "";
     }
     std::unique_ptr<char[]> buffer;
@@ -319,7 +319,7 @@
 
   // All data written.
   std::string header = ConstructDataHeader(kDataLen);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
   }
@@ -380,7 +380,7 @@
       quic::test::GetNthClientInitiatedBidirectionalStreamId(
           version_.transport_version, 0),
       quic::QUIC_STREAM_CANCELLED, 0);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     EXPECT_CALL(
         session_,
         SendRstStream(quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -400,7 +400,7 @@
   }
 
   stream_->OnStreamReset(rst);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     // Make a STOP_SENDING frame and pass it to QUIC. For V99/IETF QUIC,
     // we need both a REST_STREAM and a STOP_SENDING to effect a closed
     // stream.
@@ -433,7 +433,7 @@
   const char data[] = "hello world!";
   int data_len = strlen(data);
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(data_len);
     stream_->OnStreamFrame(quic::QuicStreamFrame(
         quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -471,7 +471,7 @@
             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
 
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(data_len);
     stream_->OnStreamFrame(quic::QuicStreamFrame(
         quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -534,7 +534,7 @@
 
   // Receive the data and close the stream during the callback.
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(data_len);
     stream_->OnStreamFrame(quic::QuicStreamFrame(
         quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -566,7 +566,7 @@
   const char data[] = "hello world!";
   int data_len = strlen(data);
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(data_len);
     stream_->OnStreamFrame(quic::QuicStreamFrame(
         quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -591,7 +591,7 @@
 
   spdy::SpdyHeaderBlock trailers;
   trailers["bar"] = "foo";
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     trailers[quic::kFinalOffsetHeaderKey] = base::NumberToString(strlen(data));
   }
 
@@ -622,7 +622,7 @@
   const char data[] = "hello world!";
   int data_len = strlen(data);
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(data_len);
     stream_->OnStreamFrame(quic::QuicStreamFrame(
         quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -652,7 +652,7 @@
 
   spdy::SpdyHeaderBlock trailers;
   trailers["bar"] = "foo";
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     trailers[quic::kFinalOffsetHeaderKey] = base::NumberToString(strlen(data));
   }
   quic::QuicHeaderList t = ProcessTrailers(trailers);
@@ -685,7 +685,7 @@
   const char data[] = "hello world!";
   int data_len = strlen(data);
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(data_len);
     stream_->OnStreamFrame(quic::QuicStreamFrame(
         quic::test::GetNthClientInitiatedBidirectionalStreamId(
@@ -711,7 +711,7 @@
   // Deliver trailers. Delegate notification is posted asynchronously.
   spdy::SpdyHeaderBlock trailers;
   trailers["bar"] = "foo";
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     trailers[quic::kFinalOffsetHeaderKey] = base::NumberToString(strlen(data));
   }
 
@@ -752,7 +752,7 @@
   const size_t kDataLen = base::size(kData1);
 
   // All data written.
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(kDataLen);
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
@@ -780,7 +780,7 @@
   ASSERT_FALSE(callback.have_result());
 
   // All data written.
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(kDataLen);
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
@@ -789,7 +789,7 @@
       .WillOnce(Return(quic::QuicConsumedData(kDataLen, true)));
   stream_->OnCanWrite();
   // Do 2 writes in version 99.
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     stream_->OnCanWrite();
   }
   ASSERT_TRUE(callback.have_result());
@@ -804,14 +804,14 @@
       base::MakeRefCounted<StringIOBuffer>("Just a small payload");
 
   // All data written.
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(buf1->size());
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
   }
   EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
       .WillOnce(Return(quic::QuicConsumedData(buf1->size(), false)));
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(buf2->size());
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
@@ -832,7 +832,7 @@
       base::MakeRefCounted<StringIOBuffer>("Just a small payload");
 
   // Only a part of the data is written.
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(buf1->size());
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
@@ -851,7 +851,7 @@
   ASSERT_FALSE(callback.have_result());
 
   // The second piece of data is written.
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(buf2->size());
     EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
         .WillOnce(Return(quic::QuicConsumedData(header.length(), false)));
@@ -859,7 +859,7 @@
   EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
       .WillOnce(Return(quic::QuicConsumedData(buf2->size(), true)));
   stream_->OnCanWrite();
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     stream_->OnCanWrite();
   }
   ASSERT_TRUE(callback.have_result());
@@ -908,7 +908,7 @@
   const char data[] = "hello world!";
 
   size_t offset = 0;
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(strlen(data));
     stream2->OnStreamFrame(quic::QuicStreamFrame(stream_id,
                                                  /*fin=*/false,
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index bd8006e..0fc3a024 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -365,3 +365,6 @@
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_use_quic_time_for_received_timestamp2,
           false)
+
+// If true, enable QUIC version h3-25.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_draft_25, false)
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 0bdd922..0dd599b 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -105,6 +105,9 @@
       return quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3
                  ? HttpResponseInfo::CONNECTION_INFO_QUIC_T050
                  : HttpResponseInfo::CONNECTION_INFO_QUIC_Q050;
+    case quic::QUIC_VERSION_IETF_DRAFT_25:
+      DCHECK(quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3);
+      return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_25;
     case quic::QUIC_VERSION_99:
       return quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3
                  ? HttpResponseInfo::CONNECTION_INFO_QUIC_T099
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index c7ca37b..d2c530d 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -573,7 +573,7 @@
   }
 
   std::string ConstructDataHeader(size_t body_len) {
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       return "";
     }
     std::unique_ptr<char[]> buffer;
@@ -1206,7 +1206,7 @@
     AddWrite(ConstructInitialSettingsPacket(packet_number++));
 
   std::string header = ConstructDataHeader(strlen(kUploadData));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
         kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
@@ -1288,7 +1288,7 @@
   if (VersionUsesHttp3(version_.transport_version))
     AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(strlen(kUploadData));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
         kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
@@ -1372,7 +1372,7 @@
   if (VersionUsesHttp3(version_.transport_version))
     AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(chunk_size);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
         kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
@@ -1459,7 +1459,7 @@
     AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(chunk_size);
 
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
         kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
@@ -1701,7 +1701,7 @@
   if (VersionUsesHttp3(version_.transport_version))
     AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(strlen(kUploadData));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
         kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
@@ -1864,7 +1864,7 @@
   if (VersionUsesHttp3(version_.transport_version))
     AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(strlen(kUploadData));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
         kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index a1294e4..eaa40de 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -617,7 +617,7 @@
   }
 
   std::string ConstructDataHeader(size_t body_len) {
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       return "";
     }
     std::unique_ptr<char[]> buffer;
@@ -2562,7 +2562,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, GoAwayWithConnectionMigrationOnPortsOnly) {
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     // GoAway is not available under version 99
     return;
   }
@@ -7060,7 +7060,7 @@
   }
 
   std::string header = ConstructDataHeader(1);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientRequestHeadersAndDataFramesPacket(
@@ -7533,7 +7533,7 @@
       quic::QuicStreamId stream_id,
       QuicTestPacketMaker* maker) {
     std::string header = "";
-    if (version_.transport_version == quic::QUIC_VERSION_99) {
+    if (version_.HasIetfQuicFrames()) {
       std::unique_ptr<char[]> buffer;
       auto header_length =
           quic::HttpEncoder::SerializeDataFrameHeader(5, &buffer);
@@ -7977,7 +7977,7 @@
                               quic::QUIC_STREAM_CANCELLED, 5, 5, 1));
   const char kBody[] = "1";
   std::string header3 = ConstructDataHeader(1);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientRequestHeadersAndDataFramesPacket(
@@ -8143,7 +8143,7 @@
       "Host: mail.example.org\r\n"
       "Connection: keep-alive\r\n\r\n";
   std::string header = ConstructDataHeader(strlen(get_request));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
@@ -8255,7 +8255,7 @@
   spdy::SpdySerializedFrame get_frame =
       spdy_util.ConstructSpdyGet("https://mail.example.org/", 1, LOWEST);
   std::string header = ConstructDataHeader(get_frame.size());
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
@@ -8374,7 +8374,7 @@
       "Host: mail.example.org\r\n"
       "Connection: keep-alive\r\n\r\n";
   std::string header = ConstructDataHeader(strlen(get_request_1));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS, ConstructClientAckAndDataPacket(
                          write_packet_index++, false,
@@ -8413,7 +8413,7 @@
       "Host: mail.example.org\r\n"
       "Connection: keep-alive\r\n\r\n";
   std::string header4 = ConstructDataHeader(strlen(get_request_2));
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientDataPacket(
@@ -8546,7 +8546,7 @@
       "Host: mail.example.org\r\n"
       "Connection: keep-alive\r\n\r\n";
   std::string header = ConstructDataHeader(strlen(get_request));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
@@ -8605,7 +8605,7 @@
   spdy::SpdySerializedFrame get_frame =
       spdy_util.ConstructSpdyGet("https://different.example.org/", 1, LOWEST);
   std::string header4 = ConstructDataHeader(get_frame.size());
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
@@ -8906,7 +8906,7 @@
       "Host: mail.example.org\r\n"
       "Connection: keep-alive\r\n\r\n";
   std::string header = ConstructDataHeader(strlen(get_request));
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
@@ -9952,7 +9952,7 @@
                    false, GetResponseHeaders("200 OK"), nullptr));
 
     std::string header = ConstructDataHeader(strlen(kGetRequest));
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       mock_quic_data[index]->AddWrite(
           SYNCHRONOUS, client_maker.MakeAckAndDataPacket(
                            packet_num++, false,
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc
index a221e7f..f62240f 100644
--- a/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -560,7 +560,7 @@
   }
 
   std::string ConstructDataHeader(size_t body_len) {
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       return "";
     }
     std::unique_ptr<char[]> buffer;
@@ -936,7 +936,7 @@
                            ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     std::string header = ConstructDataHeader(kLen1);
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
@@ -981,7 +981,7 @@
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   std::string header = ConstructDataHeader(kLen1);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data_.AddWrite(
         SYNCHRONOUS, ConstructAckAndDataPacket(write_packet_index++, 1, 1, 1,
                                                std::string(kMsg1, kLen1)));
@@ -998,7 +998,7 @@
   std::string data(numDataPackets * quic::kDefaultMaxPacketSize, 'x');
   quic::QuicStreamOffset offset = kLen1 + header.length();
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     numDataPackets++;
   }
   size_t total_data_length = 0;
@@ -1007,7 +1007,7 @@
         quic::kDefaultMaxPacketSize, version_, !kIncludeVersion,
         !kIncludeDiversificationNonce, quic::PACKET_8BYTE_CONNECTION_ID,
         quic::PACKET_1BYTE_PACKET_NUMBER, offset);
-    if (version_.transport_version == quic::QUIC_VERSION_99 && i == 0) {
+    if (version_.HasIetfQuicFrames() && i == 0) {
       // 3973 is the data frame length from packet length.
       std::string header2 = ConstructDataHeader(3973);
       mock_quic_data_.AddWrite(
@@ -1017,8 +1017,7 @@
               {header2 +
                std::string(data.c_str(), max_packet_data_length - 7)}));
       offset += max_packet_data_length - header2.length() - 1;
-    } else if (version_.transport_version == quic::QUIC_VERSION_99 &&
-               i == numDataPackets - 1) {
+    } else if (version_.HasIetfQuicFrames() && i == numDataPackets - 1) {
       mock_quic_data_.AddWrite(
           SYNCHRONOUS, ConstructDataPacket(write_packet_index++,
                                            std::string(data.c_str(), 7)));
@@ -1415,7 +1414,7 @@
                            ConstructAckPacket(write_packet_index++, 2, 1, 1));
 
   std::string header2 = ConstructDataHeader(kLen2);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
         ConstructDataPacket(write_packet_index++,
@@ -1484,7 +1483,7 @@
   mock_quic_data_.AddWrite(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header3 = ConstructDataHeader(kLen2);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data_.AddWrite(
         ASYNC, ConstructDataPacket(packet_number++, std::string(kMsg2, kLen2)));
     mock_quic_data_.AddWrite(
@@ -1817,7 +1816,7 @@
       ASYNC, ConstructServerRstPacket(2, quic::QUIC_STREAM_CANCELLED));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   std::string header = ConstructDataHeader(kLen2);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data_.AddWrite(
         ASYNC, ConstructAckAndDataPacket(packet_number++, 1, 1, 1,
                                          std::string(kMsg2, kLen2)));
@@ -1962,7 +1961,7 @@
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerRstPacket(2, quic::QUIC_STREAM_CANCELLED));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     mock_quic_data_.AddWrite(
         ASYNC, ConstructAckAndDataPacket(packet_number++, 1, 1, 1,
                                          std::string(kMsg1, kLen1)));
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 8a8abab..6c001a7 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -828,7 +828,7 @@
   }
 
   std::string ConstructDataHeader(size_t body_len) {
-    if (version_.transport_version != quic::QUIC_VERSION_99) {
+    if (!version_.HasIetfQuicFrames()) {
       return "";
     }
     std::unique_ptr<char[]> buffer;
@@ -998,7 +998,7 @@
 
 TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -1093,7 +1093,7 @@
 
 TEST_P(QuicStreamFactoryTest, RequireConfirmation) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -1140,7 +1140,7 @@
 
 TEST_P(QuicStreamFactoryTest, DontRequireConfirmationFromSameIP) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -1975,7 +1975,7 @@
 
   quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(0);
   MockQuicData socket_data(version_);
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     int packet_num = 1;
     socket_data.AddWrite(SYNCHRONOUS,
                          ConstructInitialSettingsPacket(packet_num++));
@@ -10434,7 +10434,7 @@
 
 TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -10584,7 +10584,7 @@
 // Verifies that the QUIC stream factory is initialized correctly.
 TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -10593,7 +10593,7 @@
 
 TEST_P(QuicStreamFactoryTest, MaybeInitializeWithNetworkIsolationKey) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -10825,7 +10825,7 @@
 TEST_P(QuicStreamFactoryTest,
        CryptoConfigCacheMRUWithRealRequestsAndWithNetworkIsolationKey) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -11043,7 +11043,7 @@
 
 TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -11100,7 +11100,7 @@
 
 TEST_P(QuicStreamFactoryTest, YieldAfterDuration) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -12381,7 +12381,7 @@
 TEST_P(QuicStreamFactoryTest,
        ResultAfterDNSRaceHostResolveAsyncConnectAsyncStaleMatch) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -12457,7 +12457,7 @@
 TEST_P(QuicStreamFactoryTest,
        ResultAfterDNSRaceHostResolveAsyncStaleMatchConnectAsync) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -13238,7 +13238,7 @@
 // after handshake confirmed, and then fresh resolve returns.
 TEST_P(QuicStreamFactoryTest, StaleNetworkFailedAfterHandshake) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
@@ -13318,7 +13318,7 @@
 // handshake
 TEST_P(QuicStreamFactoryTest, StaleNetworkFailedBeforeHandshake) {
   if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+      version_.HasIetfQuicFrames()) {
     // 0-rtt is not supported in IETF QUIC yet.
     return;
   }
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc
index 4bdd3fb..10234cc 100644
--- a/net/quic/quic_test_packet_maker.cc
+++ b/net/quic/quic_test_packet_maker.cc
@@ -149,7 +149,7 @@
                                                    bool include_version) {
   InitializeHeader(num, include_version);
 
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
+  if (!version_.HasIetfQuicFrames()) {
     AddQuicPingFrame();
   } else if (perspective_ == quic::Perspective::IS_CLIENT) {
     AddQuicPathChallengeFrame();
@@ -245,13 +245,12 @@
     bool include_stop_sending_if_v99) {
   InitializeHeader(num, include_version);
 
-  if (version_.transport_version != quic::QUIC_VERSION_99 ||
+  if (!version_.HasIetfQuicFrames() ||
       quic::QuicUtils::IsBidirectionalStreamId(stream_id)) {
     AddQuicRstStreamFrame(stream_id, error_code);
   }
 
-  if (include_stop_sending_if_v99 &&
-      version_.transport_version == quic::QUIC_VERSION_99) {
+  if (include_stop_sending_if_v99 && version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(stream_id, error_code);
   }
 
@@ -270,7 +269,7 @@
 
   AddQuicRstStreamFrame(rst_stream_id, rst_error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(rst_stream_id, rst_error_code);
   }
 
@@ -292,7 +291,7 @@
   AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
   AddQuicRstStreamFrame(rst_stream_id, rst_error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(rst_stream_id, rst_error_code);
   }
 
@@ -330,13 +329,12 @@
 
   AddQuicAckFrame(largest_received, smallest_received);
 
-  if (version_.transport_version != quic::QUIC_VERSION_99 ||
+  if (!version_.HasIetfQuicFrames() ||
       quic::QuicUtils::IsBidirectionalStreamId(stream_id)) {
     AddQuicRstStreamFrame(stream_id, error_code);
   }
 
-  if (version_.transport_version == quic::QUIC_VERSION_99 &&
-      include_stop_sending_if_v99) {
+  if (version_.HasIetfQuicFrames() && include_stop_sending_if_v99) {
     AddQuicStopSendingFrame(stream_id, error_code);
   }
 
@@ -358,7 +356,7 @@
 
   AddQuicRstStreamFrame(stream_id, error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(stream_id, error_code);
   }
 
@@ -380,7 +378,7 @@
 
   AddQuicRstStreamFrame(stream_id, error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(stream_id, error_code);
   }
 
@@ -404,7 +402,7 @@
   AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
   AddQuicRstStreamFrame(rst_stream_id, error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(rst_stream_id, error_code);
   }
 
@@ -431,7 +429,7 @@
   AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
   AddQuicRstStreamFrame(rst_stream_id, error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(rst_stream_id, error_code);
   }
 
@@ -656,7 +654,7 @@
 
   AddQuicRstStreamFrame(stream_id, error_code);
 
-  if (version_.transport_version == quic::QUIC_VERSION_99) {
+  if (version_.HasIetfQuicFrames()) {
     AddQuicStopSendingFrame(stream_id, error_code);
   }
 
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index fbacae8..a4adf32 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -197,6 +197,7 @@
         "pdfium/findtext_unittest.cc",
         "pdfium/pdfium_engine_exports_unittest.cc",
         "pdfium/pdfium_engine_unittest.cc",
+        "pdfium/pdfium_form_filler_unittest.cc",
         "pdfium/pdfium_page_unittest.cc",
         "pdfium/pdfium_permissions_unittest.cc",
         "pdfium/pdfium_print_unittest.cc",
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 0602f58..7a707bfb 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -3612,6 +3612,25 @@
   }
 }
 
+void PDFiumEngine::ScrollIntoView(const pp::Rect& rect) {
+  pp::Rect visible_rect = GetVisibleRect();
+  if (visible_rect.Contains(rect))
+    return;
+  // Since the focus rect is not already in the visible area, scrolling
+  // horizontally and/or vertically is required.
+  if (rect.y() < visible_rect.y() || rect.bottom() > visible_rect.bottom()) {
+    // Scroll the viewport vertically to align the top of focus rect to
+    // centre.
+    client_->ScrollToY(rect.y() * current_zoom_ - plugin_size_.height() / 2,
+                       /*compensate_for_toolbar=*/false);
+  }
+  if (rect.x() < visible_rect.x() || rect.right() > visible_rect.right()) {
+    // Scroll the viewport horizontally to align the left of focus rect to
+    // centre.
+    client_->ScrollToX(rect.x() * current_zoom_ - plugin_size_.width() / 2);
+  }
+}
+
 void PDFiumEngine::SetCaretPosition(const pp::Point& position) {
   // TODO(dsinclair): Handle caret position ...
 }
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 4b896c3..9a54bd7 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -30,6 +30,7 @@
 #include "ppapi/cpp/image_data.h"
 #include "ppapi/cpp/input_event.h"
 #include "ppapi/cpp/point.h"
+#include "ppapi/cpp/rect.h"
 #include "ppapi/cpp/var_array.h"
 #include "ppapi/utility/completion_callback_factory.h"
 #include "third_party/pdfium/public/cpp/fpdf_scopers.h"
@@ -205,6 +206,7 @@
     DISALLOW_COPY_AND_ASSIGN(MouseDownState);
   };
 
+  friend class FormFillerTest;
   friend class PDFiumFormFiller;
   friend class PDFiumTestBase;
   friend class SelectionChangeInvalidator;
@@ -564,6 +566,10 @@
   void SetSelection(const PP_PdfPageCharacterIndex& selection_start_index,
                     const PP_PdfPageCharacterIndex& selection_end_index);
 
+  // Given |rect| in document coordinates, scroll the |rect| into view if not
+  // already in view.
+  void ScrollIntoView(const pp::Rect& rect);
+
   PDFEngine::Client* const client_;
 
   // The current document layout.
diff --git a/pdf/pdfium/pdfium_form_filler.cc b/pdf/pdfium/pdfium_form_filler.cc
index c1a8d37..48dec184 100644
--- a/pdf/pdfium/pdfium_form_filler.cc
+++ b/pdf/pdfium/pdfium_form_filler.cc
@@ -12,6 +12,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "pdf/pdfium/pdfium_engine.h"
+#include "ppapi/cpp/point.h"
+#include "ppapi/cpp/rect.h"
+#include "third_party/pdfium/public/fpdf_annot.h"
 
 namespace chrome_pdf {
 
@@ -29,7 +32,7 @@
   // allows the static callbacks to be able to cast the FPDF_FORMFILLINFO in
   // callbacks to ourself instead of maintaining a map of them to
   // PDFiumEngine.
-  FPDF_FORMFILLINFO::version = 1;
+  FPDF_FORMFILLINFO::version = 2;
   FPDF_FORMFILLINFO::Release = nullptr;
   FPDF_FORMFILLINFO::FFI_Invalidate = Form_Invalidate;
   FPDF_FORMFILLINFO::FFI_OutputSelectedRect = Form_OutputSelectedRect;
@@ -45,8 +48,8 @@
   FPDF_FORMFILLINFO::FFI_SetTextFieldFocus = Form_SetTextFieldFocus;
   FPDF_FORMFILLINFO::FFI_DoURIAction = Form_DoURIAction;
   FPDF_FORMFILLINFO::FFI_DoGoToAction = Form_DoGoToAction;
+  FPDF_FORMFILLINFO::FFI_OnFocusChange = Form_OnFocusChange;
 #if defined(PDF_ENABLE_XFA)
-  FPDF_FORMFILLINFO::version = 2;
   FPDF_FORMFILLINFO::xfa_disabled = false;
   FPDF_FORMFILLINFO::FFI_EmailTo = Form_EmailTo;
   FPDF_FORMFILLINFO::FFI_DisplayCaret = Form_DisplayCaret;
@@ -63,6 +66,23 @@
   FPDF_FORMFILLINFO::FFI_OpenFile = Form_OpenFile;
   FPDF_FORMFILLINFO::FFI_GotoURL = Form_GotoURL;
   FPDF_FORMFILLINFO::FFI_GetLanguage = Form_GetLanguage;
+#else
+  FPDF_FORMFILLINFO::xfa_disabled = true;
+  FPDF_FORMFILLINFO::FFI_EmailTo = nullptr;
+  FPDF_FORMFILLINFO::FFI_DisplayCaret = nullptr;
+  FPDF_FORMFILLINFO::FFI_SetCurrentPage = nullptr;
+  FPDF_FORMFILLINFO::FFI_GetCurrentPageIndex = nullptr;
+  FPDF_FORMFILLINFO::FFI_GetPageViewRect = nullptr;
+  FPDF_FORMFILLINFO::FFI_GetPlatform = nullptr;
+  FPDF_FORMFILLINFO::FFI_PageEvent = nullptr;
+  FPDF_FORMFILLINFO::FFI_PopupMenu = nullptr;
+  FPDF_FORMFILLINFO::FFI_PostRequestURL = nullptr;
+  FPDF_FORMFILLINFO::FFI_PutRequestURL = nullptr;
+  FPDF_FORMFILLINFO::FFI_UploadTo = nullptr;
+  FPDF_FORMFILLINFO::FFI_DownloadFromURL = nullptr;
+  FPDF_FORMFILLINFO::FFI_OpenFile = nullptr;
+  FPDF_FORMFILLINFO::FFI_GotoURL = nullptr;
+  FPDF_FORMFILLINFO::FFI_GetLanguage = nullptr;
 #endif  // defined(PDF_ENABLE_XFA)
 
   if (enable_javascript) {
@@ -252,6 +272,26 @@
 }
 
 // static
+void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param,
+                                          FPDF_ANNOTATION annot,
+                                          int page_index) {
+  PDFiumEngine* engine = GetEngine(param);
+  if (!engine->PageIndexInBounds(page_index))
+    return;
+
+  FS_RECTF annot_rect;
+  if (!FPDFAnnot_GetRect(annot, &annot_rect))
+    return;
+
+  pp::Rect screen_rect = engine->pages_[page_index]->PageToScreen(
+      pp::Point(), /*zoom=*/1.0, annot_rect.left, annot_rect.top,
+      annot_rect.right, annot_rect.bottom,
+      engine->layout_.options().default_page_orientation());
+
+  engine->ScrollIntoView(screen_rect);
+}
+
+// static
 void PDFiumFormFiller::Form_DoURIAction(FPDF_FORMFILLINFO* param,
                                         FPDF_BYTESTRING uri) {
   PDFiumEngine* engine = GetEngine(param);
diff --git a/pdf/pdfium/pdfium_form_filler.h b/pdf/pdfium/pdfium_form_filler.h
index c75f09d..62c07fdc 100644
--- a/pdf/pdfium/pdfium_form_filler.h
+++ b/pdf/pdfium/pdfium_form_filler.h
@@ -12,6 +12,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "third_party/pdfium/public/fpdf_formfill.h"
+#include "third_party/pdfium/public/fpdfview.h"
 
 namespace chrome_pdf {
 
@@ -23,6 +24,8 @@
   ~PDFiumFormFiller();
 
  private:
+  friend class FormFillerTest;
+
   // FPDF_FORMFILLINFO callbacks.
   static void Form_Invalidate(FPDF_FORMFILLINFO* param,
                               FPDF_PAGE page,
@@ -55,6 +58,9 @@
                                      FPDF_WIDESTRING value,
                                      FPDF_DWORD valueLen,
                                      FPDF_BOOL is_focus);
+  static void Form_OnFocusChange(FPDF_FORMFILLINFO* param,
+                                 FPDF_ANNOTATION annot,
+                                 int page_index);
   static void Form_DoURIAction(FPDF_FORMFILLINFO* param, FPDF_BYTESTRING uri);
   static void Form_DoGoToAction(FPDF_FORMFILLINFO* param,
                                 int page_index,
diff --git a/pdf/pdfium/pdfium_form_filler_unittest.cc b/pdf/pdfium/pdfium_form_filler_unittest.cc
new file mode 100644
index 0000000..027aa3b
--- /dev/null
+++ b/pdf/pdfium/pdfium_form_filler_unittest.cc
@@ -0,0 +1,98 @@
+// 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 "pdf/pdfium/pdfium_engine.h"
+#include "pdf/pdfium/pdfium_test_base.h"
+#include "pdf/test/test_client.h"
+#include "ppapi/c/pp_point.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/pdfium/public/fpdf_annot.h"
+
+using testing::InSequence;
+
+namespace chrome_pdf {
+
+namespace {
+
+class FormFillerTestClient : public TestClient {
+ public:
+  FormFillerTestClient() = default;
+  ~FormFillerTestClient() override = default;
+  FormFillerTestClient(const FormFillerTestClient&) = delete;
+  FormFillerTestClient& operator=(const FormFillerTestClient&) = delete;
+
+  // Mock PDFEngine::Client methods.
+  MOCK_METHOD1(ScrollToX, void(int));
+  MOCK_METHOD2(ScrollToY, void(int, bool));
+};
+
+}  // namespace
+
+class FormFillerTest : public PDFiumTestBase {
+ public:
+  FormFillerTest() = default;
+  ~FormFillerTest() override = default;
+  FormFillerTest(const FormFillerTest&) = delete;
+  FormFillerTest& operator=(const FormFillerTest&) = delete;
+
+  void TriggerFormFocusChange(PDFiumEngine* engine,
+                              FPDF_ANNOTATION annot,
+                              int page_index) {
+    ASSERT_TRUE(engine);
+    engine->form_filler_.Form_OnFocusChange(&engine->form_filler_, annot,
+                                            page_index);
+  }
+};
+
+TEST_F(FormFillerTest, FormOnFocusChange) {
+  struct {
+    // Initial scroll position of the document.
+    PP_Point initial_position;
+    // Page number on which the annotation is present.
+    int page_index;
+    // The index of test annotation on page_index.
+    int annot_index;
+    // The scroll position to bring the annotation into view. (0,0) if the
+    // annotation is already in view.
+    PP_Point final_scroll_position;
+  } static constexpr test_cases[] = {
+      {{0, 0}, 0, 0, {242, 746}},   {{0, 0}, 0, 1, {510, 478}},
+      {{242, 40}, 0, 0, {0, 746}},  {{60, 758}, 0, 0, {242, 0}},
+      {{242, 758}, 0, 0, {0, 0}},   {{242, 768}, 0, 0, {0, 746}},
+      {{274, 758}, 0, 0, {242, 0}}, {{60, 40}, 1, 0, {242, 1816}}};
+
+  FormFillerTestClient client;
+  std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
+      &client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
+  ASSERT_TRUE(engine);
+  ASSERT_EQ(2, engine->GetNumberOfPages());
+  engine->PluginSizeUpdated(pp::Size(60, 40));
+
+  {
+    InSequence sequence;
+
+    for (const auto& test_case : test_cases) {
+      if (test_case.final_scroll_position.y != 0) {
+        EXPECT_CALL(client,
+                    ScrollToY(test_case.final_scroll_position.y, false));
+      }
+      if (test_case.final_scroll_position.x != 0)
+        EXPECT_CALL(client, ScrollToX(test_case.final_scroll_position.x));
+    }
+  }
+
+  for (const auto& test_case : test_cases) {
+    // Setting up the initial scroll positions.
+    engine->ScrolledToXPosition(test_case.initial_position.x);
+    engine->ScrolledToYPosition(test_case.initial_position.y);
+
+    PDFiumPage* page = GetPDFiumPageForTest(engine.get(), test_case.page_index);
+    ScopedFPDFAnnotation annot(
+        FPDFPage_GetAnnot(page->GetPage(), test_case.annot_index));
+    ASSERT_TRUE(annot);
+    TriggerFormFocusChange(engine.get(), annot.get(), test_case.page_index);
+  }
+}
+
+}  // namespace chrome_pdf
\ No newline at end of file
diff --git a/pdf/test/data/annotation_form_fields.in b/pdf/test/data/annotation_form_fields.in
new file mode 100644
index 0000000..7132cb33
--- /dev/null
+++ b/pdf/test/data/annotation_form_fields.in
@@ -0,0 +1,51 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm <<
+    /Fields [5 0 R 6 0 R]
+  >>
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 2
+  /Kids [ 3 0 R 4 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [ 0 0 612 792 ]
+  /Annots [ 5 0 R 6 0 R ]
+  /Tabs /R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [ 0 0 612 792 ]
+  /Annots [ 5 0 R ]
+  /Tabs /C
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Tx
+  /T (Sub_LeftBottom)
+  /Rect [ 200 200 220 220 ]
+>>
+endobj
+{{object 6 0}} <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Tx
+  /T (Sub_RightTop)
+  /Rect [ 401 401 421 421 ]
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/pdf/test/data/annotation_form_fields.pdf b/pdf/test/data/annotation_form_fields.pdf
new file mode 100644
index 0000000..858cc65101
--- /dev/null
+++ b/pdf/test/data/annotation_form_fields.pdf
@@ -0,0 +1,64 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm <<
+    /Fields [5 0 R 6 0 R]
+  >>
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /Count 2
+  /Kids [ 3 0 R 4 0 R ]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [ 0 0 612 792 ]
+  /Annots [ 5 0 R 6 0 R ]
+  /Tabs /R
+>>
+endobj
+4 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [ 0 0 612 792 ]
+  /Annots [ 5 0 R ]
+  /Tabs /C
+>>
+endobj
+5 0 obj <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Tx
+  /T (Sub_LeftBottom)
+  /Rect [ 200 200 220 220 ]
+>>
+endobj
+6 0 obj <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Tx
+  /T (Sub_RightTop)
+  /Rect [ 401 401 421 421 ]
+>>
+endobj
+xref
+0 7
+0000000000 65535 f 
+0000000015 00000 n 
+0000000114 00000 n 
+0000000185 00000 n 
+0000000301 00000 n 
+0000000411 00000 n 
+0000000526 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 7
+>>
+startxref
+639
+%%EOF
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index af247072..a620c1a 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -232,6 +232,7 @@
     "it2me_desktop_environment.h",
     "keyboard_layout_monitor.cc",
     "keyboard_layout_monitor.h",
+    "keyboard_layout_monitor_chromeos.cc",
     "keyboard_layout_monitor_linux.cc",
     "keyboard_layout_monitor_mac.cc",
     "keyboard_layout_monitor_win.cc",
@@ -393,6 +394,7 @@
       "continue_window_linux.cc",
       "curtain_mode_linux.cc",
       "disconnect_window_linux.cc",
+      "keyboard_layout_monitor_linux.cc",
       "me2me_desktop_environment.cc",
       "me2me_desktop_environment.h",
       "xsession_chooser_linux.cc",
diff --git a/remoting/host/keyboard_layout_monitor_chromeos.cc b/remoting/host/keyboard_layout_monitor_chromeos.cc
new file mode 100644
index 0000000..7ecdcb0
--- /dev/null
+++ b/remoting/host/keyboard_layout_monitor_chromeos.cc
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/keyboard_layout_monitor.h"
+
+#include "base/callback.h"
+
+namespace remoting {
+
+namespace {
+
+class KeyboardLayoutMonitorChromeOs : public KeyboardLayoutMonitor {
+ public:
+  explicit KeyboardLayoutMonitorChromeOs(
+      base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback) {
+  }
+  ~KeyboardLayoutMonitorChromeOs() override = default;
+  void Start() override { NOTIMPLEMENTED(); }
+};
+
+}  // namespace
+
+std::unique_ptr<KeyboardLayoutMonitor> KeyboardLayoutMonitor::Create(
+    base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback,
+    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner) {
+  return std::make_unique<KeyboardLayoutMonitorChromeOs>(std::move(callback));
+}
+
+}  // namespace remoting
diff --git a/remoting/host/keyboard_layout_monitor_linux.cc b/remoting/host/keyboard_layout_monitor_linux.cc
index 1287631..99bf3ebe 100644
--- a/remoting/host/keyboard_layout_monitor_linux.cc
+++ b/remoting/host/keyboard_layout_monitor_linux.cc
@@ -4,23 +4,596 @@
 
 #include "remoting/host/keyboard_layout_monitor.h"
 
+#include "ui/gfx/x/x11.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include "base/bind.h"
 #include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/strings/utf_string_conversion_utils.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "remoting/proto/control.pb.h"
+#include "ui/base/glib/glib_signal.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
 
 namespace remoting {
 
 namespace {
 
+class KeyboardLayoutMonitorLinux;
+
+// Deletes a pointer on the main GTK+ thread.
+class GtkThreadDeleter {
+ public:
+  template <typename T>
+  void operator()(T* p) const;
+
+ private:
+  template <typename T>
+  static gboolean DeleteOnGtkThread(gpointer p);
+};
+
+// Can be constructed on any thread, but must be started and destroyed on the
+// main GTK+ thread (i.e., the GLib global default main context).
+class GdkLayoutMonitorOnGtkThread {
+ public:
+  GdkLayoutMonitorOnGtkThread(
+      scoped_refptr<base::SequencedTaskRunner> task_runner,
+      base::WeakPtr<KeyboardLayoutMonitorLinux> weak_ptr);
+
+  // Must be called on GTK Thread
+  ~GdkLayoutMonitorOnGtkThread();
+  void Start();
+
+ private:
+  void QueryLayout();
+  static GdkFilterReturn OnXEventThunk(GdkXEvent* xevent,
+                                       GdkEvent* event,
+                                       gpointer data);
+  GdkFilterReturn OnXEvent(XEvent* xevent, GdkEvent* event);
+  CHROMEG_CALLBACK_0(GdkLayoutMonitorOnGtkThread,
+                     void,
+                     OnKeysChanged,
+                     GdkKeymap*);
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  base::WeakPtr<KeyboardLayoutMonitorLinux> weak_ptr_;
+  // xkb_event_type_ is initialized in Start(). It is only used by OnXEvent,
+  // which is only registered as a callback after xkb_event_type_ has been
+  // initialized.
+  int xkb_event_type_;
+  GdkDisplay* display_ = nullptr;
+  GdkKeymap* keymap_ = nullptr;
+  int current_group_ = 0;
+  gulong handler_id_ = 0;
+};
+
 class KeyboardLayoutMonitorLinux : public KeyboardLayoutMonitor {
  public:
-  KeyboardLayoutMonitorLinux(
-      base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback) {
-  }
-  ~KeyboardLayoutMonitorLinux() override = default;
-  void Start() override {
-    // TODO(rkjnsn): Poll keyboard layout on Linux.
-  }
+  explicit KeyboardLayoutMonitorLinux(
+      base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback);
+
+  ~KeyboardLayoutMonitorLinux() override;
+
+  void Start() override;
+
+  // Used by GdkLayoutMonitorOnGtkThread.
+  using KeyboardLayoutMonitor::kSupportedKeys;
+  void OnLayoutChanged(const protocol::KeyboardLayout& new_layout);
+
+ private:
+  static gboolean StartLayoutMonitorOnGtkThread(gpointer gdk_layout_monitor);
+
+  base::RepeatingCallback<void(const protocol::KeyboardLayout&)>
+      layout_changed_callback_;
+  // Must be deleted on the GTK thread.
+  std::unique_ptr<GdkLayoutMonitorOnGtkThread, GtkThreadDeleter>
+      gdk_layout_monitor_;
+  base::WeakPtrFactory<KeyboardLayoutMonitorLinux> weak_ptr_factory_;
 };
 
+protocol::LayoutKeyFunction KeyvalToFunction(guint keyval);
+const char* DeadKeyToUtf8String(guint keyval);
+
+template <typename T>
+void GtkThreadDeleter::operator()(T* p) const {
+  g_idle_add(DeleteOnGtkThread<T>, p);
+}
+
+// static
+template <typename T>
+gboolean GtkThreadDeleter::DeleteOnGtkThread(gpointer p) {
+  delete static_cast<T*>(p);
+  // Only run once.
+  return G_SOURCE_REMOVE;
+}
+
+GdkLayoutMonitorOnGtkThread::GdkLayoutMonitorOnGtkThread(
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    base::WeakPtr<KeyboardLayoutMonitorLinux> weak_ptr)
+    : task_runner_(std::move(task_runner)), weak_ptr_(std::move(weak_ptr)) {}
+
+GdkLayoutMonitorOnGtkThread::~GdkLayoutMonitorOnGtkThread() {
+  DCHECK(g_main_context_is_owner(g_main_context_default()));
+  if (handler_id_) {
+    g_signal_handler_disconnect(keymap_, handler_id_);
+    gdk_window_remove_filter(nullptr, OnXEventThunk, this);
+  }
+}
+
+void GdkLayoutMonitorOnGtkThread::Start() {
+  DCHECK(g_main_context_is_owner(g_main_context_default()));
+  display_ = gdk_display_get_default();
+  if (!display_) {
+    LOG(WARNING) << "No default display for layout monitoring.";
+    return;
+  }
+
+  // The keymap, as GDK sees it, is the collection of all (up to 4) enabled
+  // keyboard layouts, which it and XKB refer to as "groups". The "keys-changed"
+  // signal is only fired when this keymap, containing all enabled layouts, is
+  // changed, such as by adding, removing, or rearranging layouts. Annoyingly,
+  // it does *not* fire when the active group (layout) is changed. Indeed, for
+  // whatever reason, GDK doesn't provide *any* method of obtaining or listening
+  // for changes to the active group as far as I can tell, even though it tracks
+  // the active group internally so it can emit a "direction-changed" signal
+  // when switching between groups with different writing directions. As a
+  // result, we have to use Xkb directly to get and monitor that information,
+  // which is a pain.
+  Display* xdisplay = gdk_x11_display_get_xdisplay(display_);
+  int xkb_opcode;
+  int xkb_event;
+  int xkb_error;
+  int xkb_major = XkbMajorVersion;
+  int xkb_minor = XkbMinorVersion;
+  if (XkbQueryExtension(xdisplay, &xkb_opcode, &xkb_event, &xkb_error,
+                        &xkb_major, &xkb_minor)) {
+    xkb_event_type_ = xkb_event;
+    XkbStateRec xkb_state{};
+    XkbGetState(xdisplay, XkbUseCoreKbd, &xkb_state);
+    current_group_ = xkb_state.group;
+    gdk_window_add_filter(nullptr, OnXEventThunk, this);
+  }
+
+  keymap_ = gdk_keymap_get_for_display(display_);
+  handler_id_ = g_signal_connect(keymap_, "keys-changed",
+                                 G_CALLBACK(OnKeysChangedThunk), this);
+  QueryLayout();
+}
+
+void GdkLayoutMonitorOnGtkThread::QueryLayout() {
+  protocol::KeyboardLayout layout_message;
+
+  Display* xdisplay = gdk_x11_display_get_xdisplay(display_);
+  unsigned int shift_modifier = XkbKeysymToModifiers(xdisplay, GDK_KEY_Shift_L);
+  unsigned int numlock_modifier =
+      XkbKeysymToModifiers(xdisplay, GDK_KEY_Num_Lock);
+  unsigned int altgr_modifier =
+      XkbKeysymToModifiers(xdisplay, GDK_KEY_ISO_Level3_Shift);
+  unsigned int mod5_modifier =
+      XkbKeysymToModifiers(xdisplay, GDK_KEY_ISO_Level5_Shift);
+
+  bool have_altgr = false;
+  bool have_mod5 = false;
+
+  for (ui::DomCode key : KeyboardLayoutMonitorLinux::kSupportedKeys) {
+    // Skip single-layout IME keys for now, as they are always present in the
+    // keyboard map but not present on most keyboards. Client-side IME is likely
+    // more convenient, anyway.
+    // TODO(rkjnsn): Figure out how to show these keys only when relevant.
+    if (key == ui::DomCode::LANG1 || key == ui::DomCode::LANG2 ||
+        key == ui::DomCode::CONVERT || key == ui::DomCode::NON_CONVERT ||
+        key == ui::DomCode::KANA_MODE) {
+      continue;
+    }
+
+    std::uint32_t usb_code = ui::KeycodeConverter::DomCodeToUsbKeycode(key);
+    int keycode = ui::KeycodeConverter::DomCodeToNativeKeycode(key);
+
+    // Insert entry for USB code. It's fine to overwrite if we somehow process
+    // the same USB code twice, since the actions will be the same.
+    auto& key_actions =
+        *(*layout_message.mutable_keys())[usb_code].mutable_actions();
+
+    for (int shift_level = 0; shift_level < 8; ++shift_level) {
+      // Don't bother capturing higher shift levels if there's no configured way
+      // to access them.
+      if ((shift_level & 2 && !have_altgr) || (shift_level & 4 && !have_mod5)) {
+        continue;
+      }
+
+      // Always consider NumLock set and CapsLock unset for now.
+      unsigned int modifiers = numlock_modifier |
+                               (shift_level & 1 ? shift_modifier : 0) |
+                               (shift_level & 2 ? altgr_modifier : 0) |
+                               (shift_level & 4 ? mod5_modifier : 0);
+      guint keyval = 0;
+      gdk_keymap_translate_keyboard_state(
+          keymap_, keycode, static_cast<GdkModifierType>(modifiers),
+          current_group_, &keyval, nullptr, nullptr, nullptr);
+      if (keyval == 0) {
+        continue;
+      }
+
+      guint32 unicode = gdk_keyval_to_unicode(keyval);
+      if (unicode != 0) {
+        switch (unicode) {
+          case 0x08:
+            key_actions[shift_level].set_function(
+                protocol::LayoutKeyFunction::BACKSPACE);
+            break;
+          case 0x09:
+            key_actions[shift_level].set_function(
+                protocol::LayoutKeyFunction::TAB);
+            break;
+          case 0x0D:
+            key_actions[shift_level].set_function(
+                protocol::LayoutKeyFunction::ENTER);
+            break;
+          case 0x1B:
+            key_actions[shift_level].set_function(
+                protocol::LayoutKeyFunction::ESCAPE);
+            break;
+          case 0x7F:
+            key_actions[shift_level].set_function(
+                protocol::LayoutKeyFunction::DELETE_);
+            break;
+          default:
+            std::string utf8;
+            base::WriteUnicodeCharacter(unicode, &utf8);
+            key_actions[shift_level].set_character(utf8);
+        }
+        continue;
+      }
+
+      const char* dead_key_utf8 = DeadKeyToUtf8String(keyval);
+      if (dead_key_utf8) {
+        key_actions[shift_level].set_character(dead_key_utf8);
+        continue;
+      }
+
+      if (keyval == GDK_KEY_Num_Lock || keyval == GDK_KEY_Caps_Lock) {
+        // Don't include Num Lock or Caps Lock until we decide if / how we want
+        // to handle them.
+        // TODO(rkjnsn): Determine if supporting Num Lock / Caps Lock provides
+        // enough utility to warrant support by the soft keyboard.
+        continue;
+      }
+
+      protocol::LayoutKeyFunction function = KeyvalToFunction(keyval);
+      if (function == protocol::LayoutKeyFunction::ALT_GR) {
+        have_altgr = true;
+      } else if (function == protocol::LayoutKeyFunction::MOD5) {
+        have_altgr = true;
+      }
+      key_actions[shift_level].set_function(function);
+    }
+
+    if (key_actions.empty()) {
+      layout_message.mutable_keys()->erase(usb_code);
+    }
+  }
+
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&KeyboardLayoutMonitorLinux::OnLayoutChanged,
+                                weak_ptr_, std::move(layout_message)));
+}
+
+// static
+GdkFilterReturn GdkLayoutMonitorOnGtkThread::OnXEventThunk(GdkXEvent* xevent,
+                                                           GdkEvent* event,
+                                                           gpointer data) {
+  // GdkXEvent is documented to be castable to the window-system event type
+  // XEvent in this case.
+  return static_cast<GdkLayoutMonitorOnGtkThread*>(data)->OnXEvent(
+      static_cast<XEvent*>(xevent), event);
+}
+
+GdkFilterReturn GdkLayoutMonitorOnGtkThread::OnXEvent(XEvent* xevent,
+                                                      GdkEvent* event) {
+  if (xevent->type == xkb_event_type_) {
+    XkbEvent* xkb_event = reinterpret_cast<XkbEvent*>(xevent);
+    if (xkb_event->any.xkb_type == XkbStateNotify) {
+      int new_group = XkbStateGroup(&xkb_event->state);
+      if (new_group != current_group_) {
+        current_group_ = new_group;
+        QueryLayout();
+      }
+    }
+  }
+  // GDK also needs to process this event.
+  return GDK_FILTER_CONTINUE;
+}
+
+void GdkLayoutMonitorOnGtkThread::OnKeysChanged(GdkKeymap* keymap) {
+  QueryLayout();
+}
+
+KeyboardLayoutMonitorLinux::KeyboardLayoutMonitorLinux(
+    base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback)
+    : layout_changed_callback_(std::move(callback)), weak_ptr_factory_(this) {}
+
+KeyboardLayoutMonitorLinux::~KeyboardLayoutMonitorLinux() = default;
+
+void KeyboardLayoutMonitorLinux::Start() {
+  DCHECK(!gdk_layout_monitor_);
+  gdk_layout_monitor_.reset(new GdkLayoutMonitorOnGtkThread(
+      base::SequencedTaskRunnerHandle::Get(), weak_ptr_factory_.GetWeakPtr()));
+  g_idle_add(StartLayoutMonitorOnGtkThread, gdk_layout_monitor_.get());
+}
+
+void KeyboardLayoutMonitorLinux::OnLayoutChanged(
+    const protocol::KeyboardLayout& new_layout) {
+  layout_changed_callback_.Run(new_layout);
+}
+
+// static
+gboolean KeyboardLayoutMonitorLinux::StartLayoutMonitorOnGtkThread(
+    gpointer gdk_layout_monitor) {
+  static_cast<GdkLayoutMonitorOnGtkThread*>(gdk_layout_monitor)->Start();
+  // Only run once.
+  return G_SOURCE_REMOVE;
+}
+
+// GDK doesn't return unicode value for dead keys, so we map them here.
+const char* DeadKeyToUtf8String(guint keyval) {
+  // Some of these have spacing forms and some don't. For consistency, these are
+  // all of the form space+combining character. This file is a good resource to
+  // figure out what the various dead keys are supposed to do:
+  // https://cgit.freedesktop.org/xorg/lib/libX11/plain/nls/en_US.UTF-8/Compose.pre
+  // See also ui/events/keycodes/keysym_to_unicode.cc, which does a similar
+  // mapping.
+  switch (keyval) {
+    case GDK_KEY_dead_grave:
+      return " \xcc\x80";  // U+0300
+    case GDK_KEY_dead_acute:
+      return " \xcc\x81";  // U+0301
+    case GDK_KEY_dead_circumflex:
+      return " \xcc\x82";  // U+0302
+    case GDK_KEY_dead_tilde:
+      return " \xcc\x83";  // U+0303
+    case GDK_KEY_dead_macron:
+      return " \xcc\x84";  // U+0304
+    case GDK_KEY_dead_breve:
+      return " \xcc\x86";  // U+0306
+    case GDK_KEY_dead_abovedot:
+      return " \xcc\x87";  // U+0307
+    case GDK_KEY_dead_diaeresis:
+      return " \xcc\x88";  // U+0308
+    case GDK_KEY_dead_abovering:
+      return " \xcc\x8a";  // U+030A
+    case GDK_KEY_dead_doubleacute:
+      return " \xcc\x8b";  // U+030B
+    case GDK_KEY_dead_caron:
+      return " \xcc\x8c";  // U+030C
+    case GDK_KEY_dead_cedilla:
+      return " \xcc\xa7";  // U+0327
+    case GDK_KEY_dead_ogonek:
+      return " \xcc\xa8";  // U+0328
+    case GDK_KEY_dead_iota:
+      return " \xcd\x85";  // U+0345
+    case GDK_KEY_dead_voiced_sound:
+      return " \xe3\x82\x99";  // U+3099
+    case GDK_KEY_dead_semivoiced_sound:
+      return " \xe3\x82\x9a";  // U+309A
+    case GDK_KEY_dead_belowdot:
+      return " \xcc\xa3";  // U+0323
+    case GDK_KEY_dead_hook:
+      return " \xcc\x89";  // U+0309
+    case GDK_KEY_dead_horn:
+      return " \xcc\x9b";  // U+031B
+    case GDK_KEY_dead_stroke:
+      return " \xcc\xb7";  // U+0337
+    case GDK_KEY_dead_abovecomma:
+      return " \xcc\x93";  // U+0313
+    case GDK_KEY_dead_abovereversedcomma:
+      return " \xcc\x94";  // U+0314
+    case GDK_KEY_dead_doublegrave:
+      return " \xcc\x8f";  // U+030F
+    case GDK_KEY_dead_belowring:
+      return " \xcc\xa5";  // U+0325
+    case GDK_KEY_dead_belowmacron:
+      return " \xcc\xb1";  // U+0331
+    case GDK_KEY_dead_belowcircumflex:
+      return " \xcc\xad";  // U+032D
+    case GDK_KEY_dead_belowtilde:
+      return " \xcc\xb0";  // U+0330
+    case GDK_KEY_dead_belowbreve:
+      return " \xcc\xae";  // U+032E
+    case GDK_KEY_dead_belowdiaeresis:
+      return " \xcc\xa4";  // U+0324
+    case GDK_KEY_dead_invertedbreve:
+      return " \xcc\x91";  // U+0311
+    case GDK_KEY_dead_belowcomma:
+      return " \xcc\xa6";  // U+0326
+    case GDK_KEY_dead_currency:
+      // This one is a bit different: instead of adding a diacritic to a
+      // character, it allows entering of various currency symbols. E.g.,
+      // dead_currency+e generates the euro sign (€). Combining this dead key
+      // with space generates the general currency symbol.
+      return "\xc2\xa4";  // Currency symbol (¤), U+00A4
+    // I can't find any information about what these do. There is, e.g.,
+    // "combining latin small letter a" (U+0363) that places a tiny "a" above
+    // the preceding character (and similar for the other lower-case letters),
+    // but no equivalent capital versions. These don't show up in Compose.pre,
+    // so they're probably not used much, if at all.
+    // case GDK_KEY_dead_a:
+    // case GDK_KEY_dead_A:
+    // case GDK_KEY_dead_e:
+    // case GDK_KEY_dead_E:
+    // case GDK_KEY_dead_i:
+    // case GDK_KEY_dead_I:
+    // case GDK_KEY_dead_o:
+    // case GDK_KEY_dead_O:
+    // case GDK_KEY_dead_u:
+    // case GDK_KEY_dead_U:
+    // case GDK_KEY_dead_small_schwa:
+    // case GDK_KEY_dead_capital_schwa:
+    case GDK_KEY_dead_greek:
+      // Like dead_currency above, this key is used to generate different
+      // symbols entirely (greek letters, in this case). E.g., dead_greek+a
+      // generates Greek alpha (α). Combining this dead key with space generates
+      // the micro sign (µ), a distinct code point from Greek mu (μ), which is
+      // generated by dead_greek+m.
+      return "\xce\xbc";  // Micro symbol (μ), U+00B5
+    default:
+      return nullptr;
+  }
+}
+
+protocol::LayoutKeyFunction KeyvalToFunction(guint keyval) {
+  switch (keyval) {
+    case GDK_KEY_Control_L:
+    case GDK_KEY_Control_R:
+      return protocol::LayoutKeyFunction::CONTROL;
+    case GDK_KEY_Alt_L:
+    case GDK_KEY_Alt_R:
+      return protocol::LayoutKeyFunction::ALT;
+    case GDK_KEY_Shift_L:
+    case GDK_KEY_Shift_R:
+      return protocol::LayoutKeyFunction::SHIFT;
+    case GDK_KEY_Super_L:
+    case GDK_KEY_Super_R:
+      return protocol::LayoutKeyFunction::META;
+    case GDK_KEY_ISO_Level3_Shift:
+      return protocol::LayoutKeyFunction::ALT_GR;
+    case GDK_KEY_ISO_Level5_Shift:
+      return protocol::LayoutKeyFunction::MOD5;
+    case GDK_KEY_Multi_key:
+      return protocol::LayoutKeyFunction::COMPOSE;
+    case GDK_KEY_Num_Lock:
+      return protocol::LayoutKeyFunction::NUM_LOCK;
+    case GDK_KEY_Caps_Lock:
+      return protocol::LayoutKeyFunction::CAPS_LOCK;
+    case GDK_KEY_Scroll_Lock:
+      return protocol::LayoutKeyFunction::SCROLL_LOCK;
+    case GDK_KEY_BackSpace:
+      return protocol::LayoutKeyFunction::BACKSPACE;
+    case GDK_KEY_Return:
+    case GDK_KEY_KP_Enter:
+      return protocol::LayoutKeyFunction::ENTER;
+    case GDK_KEY_Tab:           // Unshifted
+    case GDK_KEY_ISO_Left_Tab:  // Shifted
+    case GDK_KEY_KP_Tab:
+      return protocol::LayoutKeyFunction::TAB;
+    case GDK_KEY_Insert:
+    case GDK_KEY_KP_Insert:
+      return protocol::LayoutKeyFunction::INSERT;
+    case GDK_KEY_Delete:
+    case GDK_KEY_KP_Delete:
+      return protocol::LayoutKeyFunction::DELETE_;
+    case GDK_KEY_Home:
+    case GDK_KEY_KP_Home:
+      return protocol::LayoutKeyFunction::HOME;
+    case GDK_KEY_End:
+    case GDK_KEY_KP_End:
+      return protocol::LayoutKeyFunction::END;
+    case GDK_KEY_Page_Up:
+    case GDK_KEY_KP_Page_Up:
+      return protocol::LayoutKeyFunction::PAGE_UP;
+    case GDK_KEY_Page_Down:
+    case GDK_KEY_KP_Page_Down:
+      return protocol::LayoutKeyFunction::PAGE_DOWN;
+    case GDK_KEY_Clear:
+      return protocol::LayoutKeyFunction::CLEAR;
+    case GDK_KEY_Up:
+    case GDK_KEY_KP_Up:
+      return protocol::LayoutKeyFunction::ARROW_UP;
+    case GDK_KEY_Down:
+    case GDK_KEY_KP_Down:
+      return protocol::LayoutKeyFunction::ARROW_DOWN;
+    case GDK_KEY_Left:
+    case GDK_KEY_KP_Left:
+      return protocol::LayoutKeyFunction::ARROW_LEFT;
+    case GDK_KEY_Right:
+    case GDK_KEY_KP_Right:
+      return protocol::LayoutKeyFunction::ARROW_RIGHT;
+    case GDK_KEY_F1:
+    case GDK_KEY_KP_F1:
+      return protocol::LayoutKeyFunction::F1;
+    case GDK_KEY_F2:
+    case GDK_KEY_KP_F2:
+      return protocol::LayoutKeyFunction::F2;
+    case GDK_KEY_F3:
+    case GDK_KEY_KP_F3:
+      return protocol::LayoutKeyFunction::F3;
+    case GDK_KEY_F4:
+    case GDK_KEY_KP_F4:
+      return protocol::LayoutKeyFunction::F4;
+    case GDK_KEY_F5:
+      return protocol::LayoutKeyFunction::F5;
+    case GDK_KEY_F6:
+      return protocol::LayoutKeyFunction::F6;
+    case GDK_KEY_F7:
+      return protocol::LayoutKeyFunction::F7;
+    case GDK_KEY_F8:
+      return protocol::LayoutKeyFunction::F8;
+    case GDK_KEY_F9:
+      return protocol::LayoutKeyFunction::F9;
+    case GDK_KEY_F10:
+      return protocol::LayoutKeyFunction::F10;
+    case GDK_KEY_F11:
+      return protocol::LayoutKeyFunction::F11;
+    case GDK_KEY_F12:
+      return protocol::LayoutKeyFunction::F12;
+    case GDK_KEY_F13:
+      return protocol::LayoutKeyFunction::F13;
+    case GDK_KEY_F14:
+      return protocol::LayoutKeyFunction::F14;
+    case GDK_KEY_F15:
+      return protocol::LayoutKeyFunction::F15;
+    case GDK_KEY_F16:
+      return protocol::LayoutKeyFunction::F16;
+    case GDK_KEY_F17:
+      return protocol::LayoutKeyFunction::F17;
+    case GDK_KEY_F18:
+      return protocol::LayoutKeyFunction::F18;
+    case GDK_KEY_F19:
+      return protocol::LayoutKeyFunction::F19;
+    case GDK_KEY_F20:
+      return protocol::LayoutKeyFunction::F20;
+    case GDK_KEY_F21:
+      return protocol::LayoutKeyFunction::F21;
+    case GDK_KEY_F22:
+      return protocol::LayoutKeyFunction::F22;
+    case GDK_KEY_F23:
+      return protocol::LayoutKeyFunction::F23;
+    case GDK_KEY_F24:
+      return protocol::LayoutKeyFunction::F24;
+    case GDK_KEY_Escape:
+      return protocol::LayoutKeyFunction::ESCAPE;
+    case GDK_KEY_Menu:
+      return protocol::LayoutKeyFunction::CONTEXT_MENU;
+    case GDK_KEY_Pause:
+      return protocol::LayoutKeyFunction::PAUSE;
+    case GDK_KEY_Print:    // Unshifted
+    case GDK_KEY_Sys_Req:  // Shifted
+      return protocol::LayoutKeyFunction::PRINT_SCREEN;
+    case GDK_KEY_Zenkaku_Hankaku:  // Unshifted
+    case GDK_KEY_Kanji:            // Shifted
+      return protocol::LayoutKeyFunction::HANKAKU_ZENKAKU_KANJI;
+    case GDK_KEY_Henkan:
+      return protocol::LayoutKeyFunction::HENKAN;
+    case GDK_KEY_Muhenkan:
+      return protocol::LayoutKeyFunction::MUHENKAN;
+    case GDK_KEY_Hiragana_Katakana:  // Unshifted
+    case GDK_KEY_Romaji:             // Shifted
+      return protocol::KATAKANA_HIRAGANA_ROMAJI;
+    case GDK_KEY_Eisu_toggle:
+      return protocol::LayoutKeyFunction::EISU;
+    case GDK_KEY_Hangul:
+      return protocol::LayoutKeyFunction::HAN_YEONG;
+    case GDK_KEY_Hangul_Hanja:
+      return protocol::LayoutKeyFunction::HANJA;
+    default:
+      return protocol::LayoutKeyFunction::UNKNOWN;
+  }
+}
+
 }  // namespace
 
 std::unique_ptr<KeyboardLayoutMonitor> KeyboardLayoutMonitor::Create(
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index c58addbb..94079cd8 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -134,7 +134,10 @@
     defines += [ "SK_FREETYPE_MINIMUM_RUNTIME_VERSION=(((FREETYPE_MAJOR) * 0x01000000) | ((FREETYPE_MINOR) * 0x00010000) | ((FREETYPE_PATCH) * 0x00000100))" ]
   }
 
-  defines += [ "SKIA_IMPLEMENTATION=1" ]
+  defines += [
+    "SKIA_IMPLEMENTATION=1",
+    "SK_IGNORE_MAC_OPSZ_FORCE",
+  ]
 
   if (current_cpu == "arm") {
     if (arm_use_neon) {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 12023f8..bacb144 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -11820,6 +11820,42 @@
             }
           ]
         },
+        "test": "boringssl_crypto_tests",
+        "test_target": "//third_party/boringssl:boringssl_crypto_tests"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "arm64",
+              "inside_docker": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "boringssl_ssl_tests",
+        "test_target": "//third_party/boringssl:boringssl_ssl_tests"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "arm64",
+              "inside_docker": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
         "test": "cast_runner_browsertests",
         "test_target": "//fuchsia/runners:cast_runner_browsertests"
       },
@@ -12450,6 +12486,40 @@
             }
           ]
         },
+        "test": "boringssl_crypto_tests",
+        "test_target": "//third_party/boringssl:boringssl_crypto_tests"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "boringssl_ssl_tests",
+        "test_target": "//third_party/boringssl:boringssl_ssl_tests"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
         "test": "cast_runner_browsertests",
         "test_target": "//fuchsia/runners:cast_runner_browsertests"
       },
@@ -13053,6 +13123,40 @@
             }
           ]
         },
+        "test": "boringssl_crypto_tests",
+        "test_target": "//third_party/boringssl:boringssl_crypto_tests"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
+        "test": "boringssl_ssl_tests",
+        "test_target": "//third_party/boringssl:boringssl_ssl_tests"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ]
+        },
         "test": "cast_runner_browsertests",
         "test_target": "//fuchsia/runners:cast_runner_browsertests"
       },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 3a8245e..6e0b8adef 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -94,6 +94,18 @@
       'Linux FYI GPU TSAN Release',
     ],
   },
+  'boringssl_crypto_tests': {
+    'remove_from': [
+      # https://crbug.com/1054545
+      'Fuchsia x64',
+    ],
+  },
+  'boringssl_ssl_tests': {
+    'remove_from': [
+      # https://crbug.com/1054545
+      'Fuchsia x64',
+    ],
+  },
   'breakpad_unittests': {
     'modifications': {
       'android-asan': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 50387bb..919ba59 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1235,6 +1235,8 @@
       'blink_common_unittests': {},
       'blink_heap_unittests': {},
       'blink_platform_unittests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
       'cast_runner_browsertests': {},
       'cast_runner_integration_tests': {},
       'cast_runner_unittests': {},
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 330ef81a..5aa4418 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1,23 +1,4 @@
 {
-    "AdTagging": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AdTagging"
-                    ]
-                }
-            ]
-        }
-    ],
     "AddToHomescreenMessaging": [
         {
             "platforms": [
@@ -67,21 +48,6 @@
             ]
         }
     ],
-    "AllowClientHintsToThirdParty": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "AllowClientHintsToThirdParty",
-                    "enable_features": [
-                        "AllowClientHintsToThirdParty"
-                    ]
-                }
-            ]
-        }
-    ],
     "AmpBackgroundTab": [
         {
             "platforms": [
@@ -791,27 +757,6 @@
             ]
         }
     ],
-    "AutofillNoLocalSaveOnUnmaskOrUploadSuccess": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillNoLocalSaveOnUnmaskSuccess",
-                        "AutofillNoLocalSaveOnUploadSuccess"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillProfileValidation": [
         {
             "platforms": [
@@ -1055,26 +1000,6 @@
             ]
         }
     ],
-    "AutofillUseServerCVCPrediction": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillUseServerCVCPrediction"
-                    ]
-                }
-            ]
-        }
-    ],
     "BackForwardCache": [
         {
             "platforms": [
@@ -1132,25 +1057,6 @@
             ]
         }
     ],
-    "BlinkLayoutNG": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "LayoutNG"
-                    ]
-                }
-            ]
-        }
-    ],
     "BlinkSchedulerDedicatedWorkerThrottling": [
         {
             "platforms": [
@@ -1251,25 +1157,6 @@
             ]
         }
     ],
-    "BlockPromptsIfIgnoredOften": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "BlockPromptsIfIgnoredOften",
-                    "enable_features": [
-                        "BlockPromptsIfIgnoredOften"
-                    ]
-                }
-            ]
-        }
-    ],
     "BookmarkInProductHelp": [
         {
             "platforms": [
@@ -2004,21 +1891,6 @@
             ]
         }
     ],
-    "DirectCompositionPreferNV12Overlays": [
-        {
-            "platforms": [
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DirectCompositionPreferNV12Overlays"
-                    ]
-                }
-            ]
-        }
-    ],
     "DirectCompositionUseNV12DecodeSwapChain": [
         {
             "platforms": [
@@ -2167,41 +2039,6 @@
             ]
         }
     ],
-    "DriveFS": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DriveFS"
-                    ]
-                }
-            ]
-        }
-    ],
-    "DynamicExpectCT": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "DynamicExpectCTEnabled",
-                    "enable_features": [
-                        "DynamicExpectCT"
-                    ]
-                }
-            ]
-        }
-    ],
     "DynamicTcmallocThreadCache": [
         {
             "platforms": [
@@ -2247,27 +2084,6 @@
             ]
         }
     ],
-    "EnableHistoryFaviconsGoogleServerQuery": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "EnableHistoryFaviconsGoogleServerQuery"
-                    ]
-                }
-            ]
-        }
-    ],
     "EnableMediaRouter": [
         {
             "platforms": [
@@ -2283,24 +2099,6 @@
             ]
         }
     ],
-    "EnableOverwritingPlaceholderUsernames": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "EnableOverwritingPlaceholderUsernames"
-                    ]
-                }
-            ]
-        }
-    ],
     "EnableSafetyTipUI": [
         {
             "platforms": [
@@ -3149,25 +2947,6 @@
             ]
         }
     ],
-    "LegacySymantecPKI": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20181012",
-                    "enable_features": [
-                        "LegacySymantecPKI"
-                    ]
-                }
-            ]
-        }
-    ],
     "LegacyTLSDeprecation2": [
         {
             "platforms": [
@@ -3282,21 +3061,6 @@
             ]
         }
     ],
-    "MacMDDownloadShelf": [
-        {
-            "platforms": [
-                "mac"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MacMDDownloadShelf"
-                    ]
-                }
-            ]
-        }
-    ],
     "MacSystemMediaPermissionsInfoUI": [
         {
             "platforms": [
@@ -3359,36 +3123,6 @@
             ]
         }
     ],
-    "MediaFoundationH264Encoding": [
-        {
-            "platforms": [
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MediaFoundationH264Encoding"
-                    ]
-                }
-            ]
-        }
-    ],
-    "MediaFoundationVideoCapture": [
-        {
-            "platforms": [
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MediaFoundationVideoCapture"
-                    ]
-                }
-            ]
-        }
-    ],
     "MergeBlockingNonBlockingPools": [
         {
             "platforms": [
@@ -3532,21 +3266,6 @@
             ]
         }
     ],
-    "NativeGellerizationRollout": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "ChromeOSParentalControlsSettings"
-                    ]
-                }
-            ]
-        }
-    ],
     "NativeNotifications": [
         {
             "platforms": [
@@ -3762,21 +3481,6 @@
             ]
         }
     ],
-    "OfflinePagesDescriptivePendingStatus": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "OfflinePagesDescriptivePendingStatus"
-                    ]
-                }
-            ]
-        }
-    ],
     "OfflinePagesDinoPageExperiment": [
         {
             "platforms": [
@@ -3792,37 +3496,6 @@
             ]
         }
     ],
-    "OfflinePagesInDHOpenInCCT": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "OfflinePagesInDownloadHomeOpenInCct"
-                    ]
-                }
-            ]
-        }
-    ],
-    "OfflinePagesPrefetchingSuggestions": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_Holdback",
-                    "enable_features": [
-                        "KeepPrefetchedContentSuggestions",
-                        "OfflinePagesPrefetching"
-                    ]
-                }
-            ]
-        }
-    ],
     "OmniboxAssistantVoiceSearch": [
         {
             "platforms": [
@@ -4087,25 +3760,6 @@
             ]
         }
     ],
-    "PDFClickToOpen": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "ClickToOpenPDFPlaceholder"
-                    ]
-                }
-            ]
-        }
-    ],
     "PaintHolding": [
         {
             "platforms": [
@@ -4188,63 +3842,6 @@
             ]
         }
     ],
-    "PassiveDocumentEventListeners": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PassiveDocumentEventListeners"
-                    ]
-                }
-            ]
-        }
-    ],
-    "PassiveDocumentWheelEventListeners": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PassiveDocumentWheelEventListeners"
-                    ]
-                }
-            ]
-        }
-    ],
-    "PassiveEventListenersDueToFling": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PassiveEventListenersDueToFling"
-                    ]
-                }
-            ]
-        }
-    ],
     "PauseBrowserInitiatedHeavyTrafficForP2P": [
         {
             "platforms": [
@@ -4343,21 +3940,6 @@
             ]
         }
     ],
-    "PermissionPromptUIAndroid": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "BlockPromptsEnabled",
-                    "enable_features": [
-                        "BlockPromptsIfDismissedOften"
-                    ]
-                }
-            ]
-        }
-    ],
     "PermissionPromptUIAndroidModal": [
         {
             "platforms": [
@@ -4636,25 +4218,6 @@
             ]
         }
     ],
-    "PrioritizedSimpleCacheTasks": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PrioritizedSimpleCacheTasks"
-                    ]
-                }
-            ]
-        }
-    ],
     "ProactivelySwapBrowsingInstance": [
         {
             "platforms": [
@@ -5433,27 +4996,6 @@
             ]
         }
     ],
-    "SameSiteCookieMessages": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "EnabledLaunch",
-                    "enable_features": [
-                        "CookieDeprecationMessages"
-                    ]
-                }
-            ]
-        }
-    ],
     "SavePasswordIllustration": [
         {
             "platforms": [
@@ -5512,22 +5054,6 @@
             ]
         }
     ],
-    "SearchEnginePromo": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SearchEnginePromo.ExistingDevice",
-                        "SearchEnginePromo.NewDevice"
-                    ]
-                }
-            ]
-        }
-    ],
     "SearchRankerQueryBasedMixedTypes": [
         {
             "platforms": [
@@ -5744,21 +5270,6 @@
             ]
         }
     ],
-    "StopNonTimersInBackground": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Experiment",
-                    "enable_features": [
-                        "stop-non-timers-in-background"
-                    ]
-                }
-            ]
-        }
-    ],
     "SyncButterWallet": [
         {
             "platforms": [
@@ -6231,29 +5742,6 @@
             ]
         }
     ],
-    "UKM": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows",
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "params": {
-                        "RecordSessionId": "true"
-                    },
-                    "enable_features": [
-                        "Ukm"
-                    ]
-                }
-            ]
-        }
-    ],
     "UmaAndUkmDemographics": [
         {
             "platforms": [
@@ -6910,42 +6398,6 @@
             ]
         }
     ],
-    "WebRTC-H264WithOpenH264FFmpeg": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "WebRTC-H264WithOpenH264FFmpeg"
-                    ]
-                }
-            ]
-        }
-    ],
-    "WebRTC-ICE-mDNS": [
-        {
-            "platforms": [
-                "chromeos",
-                "windows",
-                "mac",
-                "linux"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "WebRtcHideLocalIpsWithMdns"
-                    ]
-                }
-            ]
-        }
-    ],
     "WebRTC-LocalIPPermissionCheck": [
         {
             "platforms": [
@@ -7151,27 +6603,6 @@
             ]
         }
     ],
-    "history-manipulation-intervention": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows",
-                "android_webview",
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "HistoryManipulationIntervention",
-                    "enable_features": [
-                        "HistoryManipulationIntervention"
-                    ]
-                }
-            ]
-        }
-    ],
     "libvpx_for_vp8": [
         {
             "platforms": [
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index f36cbe1..1ce3f9a 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2509,6 +2509,9 @@
   kV8ArrayPrototypeHasElements = 3163,
   kV8ObjectPrototypeHasElements = 3164,
   kDisallowDocumentAccess = 3165,
+  kXRSessionRequestHitTestSource = 3166,
+  kXRSessionRequestHitTestSourceForTransientInput = 3167,
+  kXRDOMOverlay = 3168,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/scripts/generate_bindings.py b/third_party/blink/renderer/bindings/scripts/generate_bindings.py
index 73a3520..1343f9c 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_bindings.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_bindings.py
@@ -9,8 +9,8 @@
 import optparse
 import sys
 
-import bind_gen
 import web_idl
+import bind_gen
 
 
 def parse_options():
diff --git a/third_party/blink/renderer/build/scripts/PRESUBMIT.py b/third_party/blink/renderer/build/scripts/PRESUBMIT.py
index 37086d7e..cb91afe 100644
--- a/third_party/blink/renderer/build/scripts/PRESUBMIT.py
+++ b/third_party/blink/renderer/build/scripts/PRESUBMIT.py
@@ -43,6 +43,9 @@
     }, {
         'file_name': 'make_runtime_features_utilities_unittest.py',
         'affected_list': [r'.*make_runtime_features_utilities.*']
+    }, {
+        'file_name': 'make_document_policy_features_unittest.py',
+        'affected_list': [r'.*make_document_policy_features.*']
     }]
     test_commands = []
     for test in tests:
diff --git a/third_party/blink/renderer/build/scripts/make_document_policy_features.py b/third_party/blink/renderer/build/scripts/make_document_policy_features.py
index 743ce34f..1a78bb5 100644
--- a/third_party/blink/renderer/build/scripts/make_document_policy_features.py
+++ b/third_party/blink/renderer/build/scripts/make_document_policy_features.py
@@ -4,6 +4,7 @@
 
 import json5_generator
 import template_expander
+from make_document_policy_features_util import parse_default_value
 
 
 class DocumentPolicyFeatureWriter(json5_generator.Writer):
@@ -12,24 +13,6 @@
     def __init__(self, json5_file_path, output_dir):
         super(DocumentPolicyFeatureWriter, self).__init__(json5_file_path, output_dir)
 
-        def parse_default_value(default_value, value_type):
-            """ Parses default_value string to actual usable C++ expression.
-            @param default_value_str: default_value field specified in document_policy_features.json5
-            @param value_type: value_type field specified in document_policy_features.json5
-            """
-            policy_value_type = "mojom::PolicyValueType::k{}".format(value_type)
-
-            if default_value == 'max':
-                return "PolicyValue::CreateMaxPolicyValue({})".format(policy_value_type)
-            if default_value == 'min':
-                return "PolicyValue::CreateMinPolicyValue({})".format(policy_value_type)
-
-            if value_type in {'bool'}:  # types that have only one corresponding PolicyValueType
-                return "PolicyValue({})".format(default_value)
-            else:
-                return "PolicyValue({}, {})".format(default_value, policy_value_type)
-
-
         @template_expander.use_jinja('templates/' + self.file_basename + '.cc.tmpl')
         def generate_implementation():
             return {
diff --git a/third_party/blink/renderer/build/scripts/make_document_policy_features_unittest.py b/third_party/blink/renderer/build/scripts/make_document_policy_features_unittest.py
new file mode 100644
index 0000000..884d262
--- /dev/null
+++ b/third_party/blink/renderer/build/scripts/make_document_policy_features_unittest.py
@@ -0,0 +1,28 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from make_document_policy_features_util import parse_default_value
+
+
+class MakeDocumentPolicyFeaturesTest(unittest.TestCase):
+    def test_parse_default_value(self):
+        self.assertEqual(
+            parse_default_value("max", "DecDouble"),
+            "PolicyValue::CreateMaxPolicyValue(mojom::PolicyValueType::kDecDouble)")
+        self.assertEqual(
+            parse_default_value("min", "DecDouble"),
+            "PolicyValue::CreateMinPolicyValue(mojom::PolicyValueType::kDecDouble)")
+        self.assertEqual(parse_default_value("false", "Bool"), "PolicyValue(false)")
+        self.assertEqual(
+            parse_default_value("0.5", "DecDouble"),
+            "PolicyValue(0.5, mojom::PolicyValueType::kDecDouble)")
+
+        with self.assertRaises(ValueError):
+            parse_default_value("max", "NotImplemented")
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/third_party/blink/renderer/build/scripts/make_document_policy_features_util.py b/third_party/blink/renderer/build/scripts/make_document_policy_features_util.py
new file mode 100644
index 0000000..ed352caf
--- /dev/null
+++ b/third_party/blink/renderer/build/scripts/make_document_policy_features_util.py
@@ -0,0 +1,33 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def parse_default_value(default_value, value_type, recognized_types=('Bool', 'DecDouble'),
+                        single_ctor_param_types=('Bool')):
+    """ Parses default_value string to actual usable C++ expression.
+    @param default_value_str: default_value field specified in document_policy_features.json5
+    @param value_type: value_type field specified in document_policy_features.json5
+    @param recognized_types: types that are valid for value_type
+    @param single_ctor_param_types: types with single param PolicyValue constructor
+     - Bool corresponds to PolicyValue(bool) which only has one constructor param
+     - DecDouble and IncDouble both take an extra constructor param for value_type
+     in constructor PolicyValue(double, mojom::PolicyValueType)
+    @returns: a C++ expression that has type mojom::PolicyValue
+    """
+    if (value_type not in recognized_types):
+        raise ValueError("{} is not recognized as valid value_type({})".format(
+            value_type, recognized_types))
+
+    policy_value_type = "mojom::PolicyValueType::k{}".format(value_type)
+
+    if default_value == 'max':
+        return "PolicyValue::CreateMaxPolicyValue({})".format(policy_value_type)
+    if default_value == 'min':
+        return "PolicyValue::CreateMinPolicyValue({})".format(policy_value_type)
+
+    # types that have only one corresponding PolicyValueType
+    if value_type in single_ctor_param_types:
+        return "PolicyValue({})".format(default_value)
+    else:
+        return "PolicyValue({}, {})".format(default_value, policy_value_type)
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
index 60ef72b2..44af68e 100644
--- a/third_party/blink/renderer/core/animation/animation.cc
+++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -1041,15 +1041,7 @@
   //      aborted pause is false, and
   //      animation does not have a pending playback rate,
   //    abort this procedure.
-  //
-  // TODO(crbug.com/916117): Remove temporary extra condition for
-  // scroll timelines. This is needed because hold_time_ can be set using
-  // timeline.currentTime, which currently can return null. This check is to
-  // make sure we don't abort in this case.
-  if ((!hold_time_ &&
-       (timeline_ &&
-        !timeline_->IsScrollTimeline() /* Temporary extra condition */)) &&
-      !aborted_pause && !pending_playback_rate_)
+  if (!hold_time_ && !aborted_pause && !pending_playback_rate_)
     return;
 
   // 6. If animation’s hold time is resolved, let its start time be unresolved.
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
index 709b064..6835a35 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
 
 #include "base/feature_list.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -126,11 +127,20 @@
               CanvasResourceProvider::kAllowSwapChainPresentationMode;
         }
 
-        ReplaceResourceProvider(CanvasResourceProvider::CreateForCanvas(
+        base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage",
+                                      usage);
+        ReplaceResourceProvider(CanvasResourceProvider::Create(
             Size(), usage, SharedGpuContext::ContextProviderWrapper(),
             0 /* msaa_sample_count */, FilterQuality(), ColorParams(),
             presentation_mode, std::move(dispatcher),
             RenderingContext()->IsOriginTopLeft()));
+        if (ResourceProvider() && ResourceProvider()->IsValid()) {
+          base::UmaHistogramBoolean(
+              "Blink.Canvas.ResourceProviderIsAccelerated",
+              ResourceProvider()->IsAccelerated());
+          base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
+                                        ResourceProvider()->GetType());
+        }
       } else {
         DCHECK(Is2d());
         const bool want_acceleration =
@@ -177,12 +187,21 @@
         const bool is_origin_top_left =
             !want_acceleration || LowLatencyEnabled();
 
-        ReplaceResourceProvider(CanvasResourceProvider::CreateForCanvas(
+        base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage",
+                                      usage);
+        ReplaceResourceProvider(CanvasResourceProvider::Create(
             Size(), usage, SharedGpuContext::ContextProviderWrapper(),
             GetMSAASampleCountFor2dContext(), FilterQuality(), ColorParams(),
             presentation_mode, std::move(dispatcher), is_origin_top_left));
 
         if (ResourceProvider()) {
+          if (ResourceProvider()->IsValid()) {
+            base::UmaHistogramBoolean(
+                "Blink.Canvas.ResourceProviderIsAccelerated",
+                ResourceProvider()->IsAccelerated());
+            base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
+                                          ResourceProvider()->GetType());
+          }
           ResourceProvider()->SetFilterQuality(FilterQuality());
           ResourceProvider()->SetResourceRecyclingEnabled(true);
         }
diff --git a/third_party/blink/renderer/core/html/forms/resources/month_picker.js b/third_party/blink/renderer/core/html/forms/resources/month_picker.js
index 06aaa38a..6e655ce5 100644
--- a/third_party/blink/renderer/core/html/forms/resources/month_picker.js
+++ b/third_party/blink/renderer/core/html/forms/resources/month_picker.js
@@ -92,8 +92,7 @@
     this.todayButton_.element.classList.add(MonthPicker.ClassNameTodayButton);
     const monthContainingToday = Month.createFromToday();
     this.todayButton_.setDisabled(
-        monthContainingToday < this.minimumMonth_ ||
-        monthContainingToday > this.maximumMonth_);
+        !this.yearListView_.isValid(monthContainingToday));
     this.todayButton_.on(
         CalendarNavigationButton.EventTypeButtonClick,
         this.onTodayButtonClick_);
@@ -107,7 +106,6 @@
   onKeyDown_ = (event) => {
     switch (event.key) {
       case 't':
-      case 'Enter':
         if (this.selectedMonth) {
           window.pagePopupController.setValueAndClosePopup(
               0, this.selectedMonth.toString());
@@ -115,6 +113,18 @@
           window.pagePopupController.closePopup();
         }
         break;
+      case 'Enter':
+        // Don't do anything here if user has hit Enter on 'This month'
+        // button.  We'll handle that in this.onTodayButtonClick_.
+        if (!event.target.matches('.calendar-navigation-button')) {
+          if (this.selectedMonth) {
+            window.pagePopupController.setValueAndClosePopup(
+                0, this.selectedMonth.toString());
+          } else {
+            window.pagePopupController.closePopup();
+          }
+        }
+        break;
       case 'Escape':
         if (!this.selectedMonth ||
             (this.selectedMonth.equals(this.initialSelectedMonth))) {
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 1ec779a..9c0d8c8b 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -610,14 +610,8 @@
   // FIXME: Not sure if we should we be doing anything with the AccelerationHint
   // argument here? Currently we use unacceleration mode.
   std::unique_ptr<CanvasResourceProvider> resource_provider =
-      CanvasResourceProvider::Create(
-          intrinsic_size,
-          CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
-          nullptr,  // context_provider_wrapper
-          0,        // msaa_sample_count
-          kLow_SkFilterQuality, CanvasColorParams(),
-          CanvasResourceProvider::kDefaultPresentationMode,
-          nullptr);  // canvas_resource_dispatcher
+      CanvasResourceProvider::CreateBitmapProvider(
+          intrinsic_size, kLow_SkFilterQuality, CanvasColorParams());
   if (!resource_provider) {
     *status = kInvalidSourceImageStatus;
     return nullptr;
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 2322949..2718b43 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -235,15 +235,15 @@
     bool fallback_to_software) {
   IntSize size(info.width(), info.height());
   CanvasColorParams color_params(info);
-  bool is_origin_top_left = source_image->IsOriginTopLeft();
 
   if (context_provider) {
     uint32_t usage_flags =
         context_provider->ContextProvider()
             ->SharedImageInterface()
             ->UsageForMailbox(source_image->GetMailboxHolder().mailbox);
-    auto resource_provider = CanvasResourceProvider::CreateAccelerated(
-        size, context_provider, color_params, is_origin_top_left, usage_flags);
+    auto resource_provider = CanvasResourceProvider::CreateSharedImageProvider(
+        size, context_provider, kLow_SkFilterQuality, color_params,
+        source_image->IsOriginTopLeft(), usage_flags);
     if (resource_provider)
       return resource_provider;
 
@@ -251,14 +251,8 @@
       return nullptr;
   }
 
-  unsigned msaa_sample_count = 0;
-  SkFilterQuality filter_quality = kLow_SkFilterQuality;
-  uint8_t presentation_mode = CanvasResourceProvider::kDefaultPresentationMode;
-  base::WeakPtr<CanvasResourceDispatcher> dispatcher = nullptr;
-  return CanvasResourceProvider::Create(
-      size, CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
-      context_provider, msaa_sample_count, filter_quality, color_params,
-      presentation_mode, dispatcher);
+  return CanvasResourceProvider::CreateBitmapProvider(
+      size, kLow_SkFilterQuality, color_params);
 }
 
 scoped_refptr<StaticBitmapImage> FlipImageVertically(
@@ -661,16 +655,11 @@
 
   // TODO(fserb): this shouldn't be software?
   std::unique_ptr<CanvasResourceProvider> resource_provider =
-      CanvasResourceProvider::Create(
+      CanvasResourceProvider::CreateBitmapProvider(
           IntSize(video->videoWidth(), video->videoHeight()),
-          CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
-          nullptr,  // context_provider_wrapper
-          0,        // msaa_sample_count
           kLow_SkFilterQuality,
-          CanvasColorParams(),  // TODO: set color space here to avoid clamping
-          CanvasResourceProvider::kDefaultPresentationMode,
-          nullptr,           // canvas_resource_dispatcher
-          IsAccelerated());  // is_origin_top_left
+          CanvasColorParams());  // TODO: set color space here to avoid clamping
+
   if (!resource_provider)
     return;
 
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index ca88648..bb564955 100644
--- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/metrics/histogram_functions.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/css/css_font_selector.h"
 #include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
@@ -397,13 +398,24 @@
     base::WeakPtr<CanvasResourceDispatcher> dispatcher_weakptr =
         HasPlaceholderCanvas() ? GetOrCreateResourceDispatcher()->GetWeakPtr()
                                : nullptr;
+    base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage", usage);
 
-    ReplaceResourceProvider(CanvasResourceProvider::CreateForCanvas(
-        surface_size, usage, SharedGpuContext::ContextProviderWrapper(), 0,
-        FilterQuality(), context_->ColorParams(), presentation_mode,
-        std::move(dispatcher_weakptr), false /* is_origin_top_left */));
+    if (usage ==
+        CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage) {
+      ReplaceResourceProvider(CanvasResourceProvider::CreateBitmapProvider(
+          surface_size, FilterQuality(), context_->ColorParams()));
+    } else {
+      ReplaceResourceProvider(CanvasResourceProvider::Create(
+          surface_size, usage, SharedGpuContext::ContextProviderWrapper(), 0,
+          FilterQuality(), context_->ColorParams(), presentation_mode,
+          std::move(dispatcher_weakptr), false /* is_origin_top_left */));
+    }
 
     if (ResourceProvider() && ResourceProvider()->IsValid()) {
+      base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
+                                ResourceProvider()->IsAccelerated());
+      base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
+                                    ResourceProvider()->GetType());
       ResourceProvider()->Clear();
 
       if (needs_matrix_clip_restore_) {
diff --git a/third_party/blink/renderer/core/page/drag_image.cc b/third_party/blink/renderer/core/page/drag_image.cc
index dbfe952..cc1acf3b 100644
--- a/third_party/blink/renderer/core/page/drag_image.cc
+++ b/third_party/blink/renderer/core/page/drag_image.cc
@@ -203,14 +203,8 @@
   scaled_image_size.Scale(device_scale_factor);
   // TODO(fserb): are we sure this should be software?
   std::unique_ptr<CanvasResourceProvider> resource_provider(
-      CanvasResourceProvider::Create(
-          scaled_image_size,
-          CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
-          nullptr,  // context_provider_wrapper
-          0,        // msaa_sample_count
-          kLow_SkFilterQuality, CanvasColorParams(),
-          CanvasResourceProvider::kDefaultPresentationMode,
-          nullptr));  // canvas_resource_dispatcher
+      CanvasResourceProvider::CreateBitmapProvider(
+          scaled_image_size, kLow_SkFilterQuality, CanvasColorParams()));
   if (!resource_provider)
     return nullptr;
 
diff --git a/third_party/blink/renderer/core/timing/performance_mark.cc b/third_party/blink/renderer/core/timing/performance_mark.cc
index 9ab4f7c..6e43a32 100644
--- a/third_party/blink/renderer/core/timing/performance_mark.cc
+++ b/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/core/performance_entry_names.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/performance.h"
-#include "third_party/blink/renderer/core/timing/performance_user_timing.h"
+#include "third_party/blink/renderer/core/timing/performance_mark_options.h"
 #include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
 #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
 
@@ -27,10 +27,49 @@
 
 // static
 PerformanceMark* PerformanceMark::Create(ScriptState* script_state,
-                                         const AtomicString& name,
-                                         double start_time,
-                                         const ScriptValue& detail,
+                                         const AtomicString& mark_name,
+                                         PerformanceMarkOptions* mark_options,
                                          ExceptionState& exception_state) {
+  Performance* performance = nullptr;
+  bool is_worker_global_scope = false;
+  if (LocalDOMWindow* window = LocalDOMWindow::From(script_state)) {
+    performance = DOMWindowPerformance::performance(*window);
+  } else if (auto* scope = DynamicTo<WorkerGlobalScope>(
+                 ExecutionContext::From(script_state))) {
+    performance = WorkerGlobalScopePerformance::performance(*scope);
+    is_worker_global_scope = true;
+  }
+  DCHECK(performance);
+
+  DOMHighResTimeStamp start = 0.0;
+  ScriptValue detail = ScriptValue::CreateNull(script_state->GetIsolate());
+  if (mark_options) {
+    if (mark_options->hasStartTime()) {
+      start = mark_options->startTime();
+      if (start < 0.0) {
+        exception_state.ThrowTypeError("'" + mark_name +
+                                       "' cannot have a negative start time.");
+        return nullptr;
+      }
+    } else {
+      start = performance->now();
+    }
+
+    detail = mark_options->detail();
+  } else {
+    start = performance->now();
+  }
+
+  if (!is_worker_global_scope &&
+      PerformanceTiming::GetAttributeMapping().Contains(mark_name)) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kSyntaxError,
+        "'" + mark_name +
+            "' is part of the PerformanceTiming interface, and "
+            "cannot be used as a mark name.");
+    return nullptr;
+  }
+
   scoped_refptr<SerializedScriptValue> serialized_detail;
   if (detail.IsEmpty()) {
     serialized_detail = SerializedScriptValue::NullValue();
@@ -42,31 +81,7 @@
       return nullptr;
   }
   return MakeGarbageCollected<PerformanceMark>(
-      name, start_time, std::move(serialized_detail), exception_state);
-}
-
-// static
-PerformanceMark* PerformanceMark::Create(ScriptState* script_state,
-                                         const AtomicString& mark_name,
-                                         PerformanceMarkOptions* mark_options,
-                                         ExceptionState& exception_state) {
-  Performance* performance = nullptr;
-  if (LocalDOMWindow* window = LocalDOMWindow::From(script_state)) {
-    performance = DOMWindowPerformance::performance(*window);
-    DCHECK(performance);
-  } else if (auto* scope = DynamicTo<WorkerGlobalScope>(
-                 ExecutionContext::From(script_state))) {
-    performance = WorkerGlobalScopePerformance::performance(*scope);
-    DCHECK(performance);
-  }
-
-  if (performance) {
-    return performance->GetUserTiming().CreatePerformanceMark(
-        script_state, mark_name, mark_options, exception_state);
-  }
-  exception_state.ThrowTypeError(
-      "PerformanceMark: no 'worker' or 'window' in current context.");
-  return nullptr;
+      mark_name, start, std::move(serialized_detail), exception_state);
 }
 
 AtomicString PerformanceMark::entryType() const {
diff --git a/third_party/blink/renderer/core/timing/performance_mark.h b/third_party/blink/renderer/core/timing/performance_mark.h
index 6d16cc16..b4d4b5e 100644
--- a/third_party/blink/renderer/core/timing/performance_mark.h
+++ b/third_party/blink/renderer/core/timing/performance_mark.h
@@ -43,18 +43,17 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static PerformanceMark* Create(ScriptState* script_state,
-                                 const AtomicString& name,
-                                 double start_time,
-                                 const ScriptValue& detail,
-                                 ExceptionState& exception_state);
-
-  // This method is required by the constructor defined in performance_mark.idl.
+  // This method corresponds to the PerformanceMark constructor defined in the
+  // User Timing L3 spec
+  // (https://w3c.github.io/user-timing/#the-performancemark-constructor). It
+  // gets called as a subroutine of the `performance.mark` method as well as
+  // whenever script runs `new PerformanceMark(..)`.
   static PerformanceMark* Create(ScriptState*,
                                  const AtomicString& mark_name,
                                  PerformanceMarkOptions*,
                                  ExceptionState&);
 
+  // This constructor is only public so that MakeGarbageCollected can call it.
   PerformanceMark(const AtomicString& name,
                   double start_time,
                   scoped_refptr<SerializedScriptValue>,
diff --git a/third_party/blink/renderer/core/timing/performance_mark.idl b/third_party/blink/renderer/core/timing/performance_mark.idl
index 81fa84e5..c37a355 100644
--- a/third_party/blink/renderer/core/timing/performance_mark.idl
+++ b/third_party/blink/renderer/core/timing/performance_mark.idl
@@ -28,6 +28,6 @@
 [
 Exposed=(Window,Worker)
 ] interface PerformanceMark : PerformanceEntry {
-    [CallWith=ScriptState, RaisesException] constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {});
+    [MeasureAs=UserTimingL3, CallWith=ScriptState, RaisesException] constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {});
     [CallWith=ScriptState] readonly attribute any detail;
 };
diff --git a/third_party/blink/renderer/core/timing/performance_mark_test.cc b/third_party/blink/renderer/core/timing/performance_mark_test.cc
index 913f1a6..bf8ecf7 100644
--- a/third_party/blink/renderer/core/timing/performance_mark_test.cc
+++ b/third_party/blink/renderer/core/timing/performance_mark_test.cc
@@ -14,26 +14,6 @@
 
 namespace blink {
 
-TEST(PerformanceMarkTest, CreateWithScriptValue) {
-  V8TestingScope scope;
-
-  ExceptionState& exception_state = scope.GetExceptionState();
-  ScriptState* script_state = scope.GetScriptState();
-  v8::Isolate* isolate = scope.GetIsolate();
-  scoped_refptr<SerializedScriptValue> payload_string =
-      SerializedScriptValue::Create(String("some-payload"));
-  ScriptValue script_value(isolate, payload_string->Deserialize(isolate));
-
-  PerformanceMark* pm = PerformanceMark::Create(script_state, "mark-name",
-                                                /*start_time=*/0.0,
-                                                script_value, exception_state);
-
-  ASSERT_EQ(pm->entryType(), performance_entry_names::kMark);
-  ASSERT_EQ(pm->EntryTypeEnum(), PerformanceEntry::EntryType::kMark);
-  ASSERT_EQ(payload_string->Deserialize(isolate),
-            pm->detail(script_state).V8Value());
-}
-
 TEST(PerformanceMarkTest, CreateWithOptions) {
   V8TestingScope scope;
 
@@ -49,7 +29,6 @@
 
   PerformanceMark* pm = PerformanceMark::Create(script_state, "mark-name",
                                                 options, exception_state);
-
   ASSERT_EQ(pm->entryType(), performance_entry_names::kMark);
   ASSERT_EQ(pm->EntryTypeEnum(), PerformanceEntry::EntryType::kMark);
   ASSERT_EQ(payload_string->Deserialize(isolate),
diff --git a/third_party/blink/renderer/core/timing/performance_observer_test.cc b/third_party/blink/renderer/core/timing/performance_observer_test.cc
index e793fdbc..aa3025d3 100644
--- a/third_party/blink/renderer/core/timing/performance_observer_test.cc
+++ b/third_party/blink/renderer/core/timing/performance_observer_test.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/timing/layout_shift.h"
 #include "third_party/blink/renderer/core/timing/performance.h"
 #include "third_party/blink/renderer/core/timing/performance_mark.h"
+#include "third_party/blink/renderer/core/timing/performance_mark_options.h"
 #include "third_party/blink/renderer/core/timing/window_performance.h"
 
 namespace blink {
@@ -88,9 +89,10 @@
   NonThrowableExceptionState exception_state;
   Initialize(scope.GetScriptState());
 
-  ScriptValue empty_value;
+  PerformanceMarkOptions* options = PerformanceMarkOptions::Create();
+  options->setStartTime(1234);
   Persistent<PerformanceEntry> entry = PerformanceMark::Create(
-      scope.GetScriptState(), "m", 1234, empty_value, exception_state);
+      scope.GetScriptState(), "m", options, exception_state);
   EXPECT_EQ(0, NumPerformanceEntries());
 
   observer_->EnqueuePerformanceEntry(*entry);
@@ -102,9 +104,10 @@
   NonThrowableExceptionState exception_state;
   Initialize(scope.GetScriptState());
 
-  ScriptValue empty_value;
+  PerformanceMarkOptions* options = PerformanceMarkOptions::Create();
+  options->setStartTime(1234);
   Persistent<PerformanceEntry> entry = PerformanceMark::Create(
-      scope.GetScriptState(), "m", 1234, empty_value, exception_state);
+      scope.GetScriptState(), "m", options, exception_state);
   EXPECT_EQ(0, NumPerformanceEntries());
 
   observer_->EnqueuePerformanceEntry(*entry);
@@ -119,9 +122,10 @@
   NonThrowableExceptionState exception_state;
   Initialize(scope.GetScriptState());
 
-  ScriptValue empty_value;
+  PerformanceMarkOptions* options = PerformanceMarkOptions::Create();
+  options->setStartTime(1234);
   Persistent<PerformanceEntry> entry = PerformanceMark::Create(
-      scope.GetScriptState(), "m", 1234, empty_value, exception_state);
+      scope.GetScriptState(), "m", options, exception_state);
   EXPECT_EQ(0, NumPerformanceEntries());
 
   observer_->EnqueuePerformanceEntry(*entry);
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.cc b/third_party/blink/renderer/core/timing/performance_user_timing.cc
index e716f1a9..e7fe5a5 100644
--- a/third_party/blink/renderer/core/timing/performance_user_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_user_timing.cc
@@ -65,36 +65,7 @@
     const AtomicString& mark_name,
     PerformanceMarkOptions* mark_options,
     ExceptionState& exception_state) {
-  DOMHighResTimeStamp start = 0.0;
-  if (mark_options && mark_options->hasStartTime()) {
-    start = mark_options->startTime();
-    if (start < 0.0) {
-      exception_state.ThrowTypeError("'" + mark_name +
-                                     "' cannot have a negative start time.");
-      return nullptr;
-    }
-  } else {
-    start = performance_->now();
-  }
-
-  ScriptValue detail = ScriptValue::CreateNull(script_state->GetIsolate());
-  if (mark_options)
-    detail = mark_options->detail();
-
-  bool is_worker_global_scope =
-      performance_->GetExecutionContext() &&
-      performance_->GetExecutionContext()->IsWorkerGlobalScope();
-  if (!is_worker_global_scope &&
-      PerformanceTiming::GetAttributeMapping().Contains(mark_name)) {
-    exception_state.ThrowDOMException(
-        DOMExceptionCode::kSyntaxError,
-        "'" + mark_name +
-            "' is part of the PerformanceTiming interface, and "
-            "cannot be used as a mark name.");
-    return nullptr;
-  }
-
-  return PerformanceMark::Create(script_state, mark_name, start, detail,
+  return PerformanceMark::Create(script_state, mark_name, mark_options,
                                  exception_state);
 }
 
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
index d08e2f0..d142f429 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -164,6 +164,8 @@
     const char* attribute_name_for_exception,
     TrustedTypeViolationKind violation_kind,
     TrustedTypeViolationKind violation_kind_when_default_policy_failed) {
+  if (!doc)
+    return script;
   bool require_trusted_type =
       RequireTrustedTypesCheck(doc->ToExecutionContext());
   if (!require_trusted_type)
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index a1d8f79..755a8bb 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -8073,15 +8073,12 @@
     return resource_provider;
   }
 
-  // TODO(fserb): why is this software?
-  std::unique_ptr<CanvasResourceProvider> temp(CanvasResourceProvider::Create(
-      size, CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
-      nullptr,  // context_provider_wrapper
-      0,        // msaa_sample_count,
-      kLow_SkFilterQuality,
-      CanvasColorParams(),  // TODO: should this use the canvas's colorspace?
-      CanvasResourceProvider::kDefaultPresentationMode,
-      nullptr));  // canvas_resource_dispatcher
+  // TODO(fserb): why is this a BITMAP?
+  std::unique_ptr<CanvasResourceProvider> temp(
+      CanvasResourceProvider::CreateBitmapProvider(
+          size, kLow_SkFilterQuality,
+          CanvasColorParams()));  // TODO: should this use the canvas's
+
   if (!temp)
     return nullptr;
   i = std::min(resource_providers_.size() - 1, i);
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc
index e96cb6f..78fa75b 100644
--- a/third_party/blink/renderer/modules/xr/xr.cc
+++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -425,6 +425,8 @@
       XRSessionFeature::REF_SPACE_BOUNDED_FLOOR, session);
   auto feature_request_unbounded =
       GetFeatureRequestStatus(XRSessionFeature::REF_SPACE_UNBOUNDED, session);
+  auto feature_request_dom_overlay =
+      GetFeatureRequestStatus(XRSessionFeature::DOM_OVERLAY, session);
 
   ukm::builders::XR_WebXR_SessionRequest(ukm_source_id_)
       .SetMode(static_cast<int64_t>(mode_))
@@ -437,6 +439,15 @@
       .SetFeature_Unbounded(static_cast<int64_t>(feature_request_unbounded))
       .Record(doc->UkmRecorder());
 
+  // If the session was successfully created and DOM overlay was requested,
+  // count this as a use of the DOM overlay feature.
+  if (session && status == SessionRequestStatus::kSuccess &&
+      feature_request_dom_overlay !=
+          device::mojom::XRSessionFeatureRequestStatus::kNotRequested) {
+    UseCounter::Count(session->GetExecutionContext(),
+                      WebFeature::kXRDOMOverlay);
+  }
+
   if (session && metrics_recorder) {
     mojo::Remote<device::mojom::blink::XRSessionMetricsRecorder> recorder(
         std::move(metrics_recorder));
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc
index 391d83f2..34efa7f4 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -1557,7 +1557,9 @@
   // Build up our added array, and update the frame id of any active input
   // sources so we can flag the ones that are no longer active.
   for (const auto& input_state : input_states) {
-    DVLOG(2) << __func__ << ": input_state->primary_input_pressed="
+    DVLOG(2) << __func__
+             << ": input_state->source_id=" << input_state->source_id
+             << " input_state->primary_input_pressed="
              << input_state->primary_input_pressed
              << " clicked=" << input_state->primary_input_clicked;
 
diff --git a/third_party/blink/renderer/modules/xr/xr_session.idl b/third_party/blink/renderer/modules/xr/xr_session.idl
index 7d17090..c1a8ec6 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.idl
+++ b/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -58,8 +58,8 @@
   [CallWith=ScriptState, Measure, RaisesException] Promise<void> end();
 
   // https://github.com/immersive-web/hit-test/blob/master/hit-testing-explainer.md
-  [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, RaisesException]
+  [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, MeasureAs=XRSessionRequestHitTestSource, RaisesException]
   Promise<XRHitTestSource> requestHitTestSource(XRHitTestOptionsInit options);
-  [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, RaisesException]
+  [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, MeasureAs=XRSessionRequestHitTestSourceForTransientInput, RaisesException]
   Promise<XRTransientInputHitTestSource> requestHitTestSourceForTransientInput(XRTransientInputHitTestOptionsInit options);
 };
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
index cf5ce78..921cef65 100644
--- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
+++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -394,13 +394,14 @@
   auto image_info = skia_image->imageInfo()
                         .makeColorSpace(color_space)
                         .makeColorType(color_type);
+
   auto usage_flags = ContextProviderWrapper()
                          ->ContextProvider()
                          ->SharedImageInterface()
                          ->UsageForMailbox(mailbox_);
-  auto provider = CanvasResourceProvider::CreateAccelerated(
-      Size(), ContextProviderWrapper(), CanvasColorParams(image_info),
-      IsOriginTopLeft(), usage_flags);
+  auto provider = CanvasResourceProvider::CreateSharedImageProvider(
+      Size(), ContextProviderWrapper(), kLow_SkFilterQuality,
+      CanvasColorParams(image_info), IsOriginTopLeft(), usage_flags);
   if (!provider) {
     return nullptr;
   }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 2c855dd..4fbffc09 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -45,8 +45,6 @@
       const IntSize& size,
       SkFilterQuality filter_quality,
       const CanvasColorParams& color_params,
-      base::WeakPtr<WebGraphicsContext3DProviderWrapper>
-          context_provider_wrapper,
       base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
       : CanvasResourceProvider(kBitmap,
                                size,
@@ -54,7 +52,7 @@
                                filter_quality,
                                color_params,
                                /*is_origin_top_left=*/true,
-                               std::move(context_provider_wrapper),
+                               /*context_provider_wrapper=*/nullptr,
                                std::move(resource_dispatcher)) {}
 
   ~CanvasResourceProviderBitmap() override = default;
@@ -96,7 +94,6 @@
       : CanvasResourceProviderBitmap(size,
                                      filter_quality,
                                      color_params,
-                                     nullptr,  // context_provider_wrapper
                                      std::move(resource_dispatcher)) {
     DCHECK(ResourceDispatcher());
     type_ = kSharedBitmap;
@@ -618,10 +615,6 @@
 
 const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
     CanvasResourceProvider::ResourceUsage usage) {
-  static const Vector<CanvasResourceType> kSoftwareFallbackList({
-      CanvasResourceType::kBitmap,
-  });
-
   static const Vector<CanvasResourceType> kAcceleratedFallbackList({
       CanvasResourceType::kSharedImage,
       // Fallback to software
@@ -664,9 +657,11 @@
                     kCompositedFallbackList.begin(),
                     kCompositedFallbackList.end()));
 
+  static const Vector<CanvasResourceType> kEmptyList;
   switch (usage) {
     case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
-      return kSoftwareFallbackList;
+      NOTREACHED();
+      return kEmptyList;
     case CanvasResourceProvider::ResourceUsage::
         kSoftwareCompositedResourceUsage:
       return kCompositedFallbackList;
@@ -684,66 +679,14 @@
     case CanvasResourceProvider::ResourceUsage::
         kSoftwareCompositedDirect2DResourceUsage:
       NOTREACHED();
-      static const Vector<CanvasResourceType> kEmptyList;
       return kEmptyList;
   }
   NOTREACHED();
+  return kEmptyList;
 }
 
 }  // unnamed namespace
 
-std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::CreateForCanvas(
-    const IntSize& size,
-    ResourceUsage usage,
-    base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
-    unsigned msaa_sample_count,
-    SkFilterQuality filter_quality,
-    const CanvasColorParams& color_params,
-    uint8_t presentation_mode,
-    base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
-    bool is_origin_top_left) {
-  base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage", usage);
-
-  std::unique_ptr<CanvasResourceProvider> provider = Create(
-      size, usage, context_provider_wrapper, msaa_sample_count, filter_quality,
-      color_params, presentation_mode, resource_dispatcher, is_origin_top_left);
-
-  if (provider && provider->IsValid()) {
-    base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
-                              provider->IsAccelerated());
-    base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
-                                  provider->type_);
-  }
-
-  return provider;
-}
-
-std::unique_ptr<CanvasResourceProvider>
-CanvasResourceProvider::CreateAccelerated(
-    const IntSize& size,
-    base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
-    const CanvasColorParams& color_params,
-    bool is_origin_top_left,
-    uint32_t shared_image_usage_flags) {
-  const auto& caps =
-      context_provider_wrapper->ContextProvider()->GetCapabilities();
-  if (size.Width() > caps.max_texture_size ||
-      size.Height() > caps.max_texture_size) {
-    return nullptr;
-  }
-
-  if (!IsGMBAllowed(size, color_params, caps))
-    shared_image_usage_flags &= ~gpu::SHARED_IMAGE_USAGE_SCANOUT;
-
-  auto provider = std::make_unique<CanvasResourceProviderSharedImage>(
-      size, 0 /* msaa_sample_count */, kLow_SkFilterQuality, color_params,
-      context_provider_wrapper, nullptr /* resource_dispatcher*/,
-      is_origin_top_left, true /* is_accelerated */, shared_image_usage_flags);
-  if (provider->IsValid())
-    return provider;
-
-  return nullptr;
-}
 
 std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
     const IntSize& size,
@@ -755,6 +698,9 @@
     uint8_t presentation_mode,
     base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
     bool is_origin_top_left) {
+  DCHECK_EQ(msaa_sample_count, 0u);
+  DCHECK(usage != ResourceUsage::kSoftwareResourceUsage);
+
   std::unique_ptr<CanvasResourceProvider> provider;
 
   bool is_gpu_memory_buffer_image_allowed = false;
@@ -767,7 +713,7 @@
     const int max_texture_size = context_capabilities.max_texture_size;
 
     if (size.Width() > max_texture_size || size.Height() > max_texture_size)
-      usage = ResourceUsage::kSoftwareResourceUsage;
+      return CreateBitmapProvider(size, filter_quality, color_params);
 
     is_gpu_memory_buffer_image_allowed =
         (presentation_mode & kAllowImageChromiumPresentationMode) &&
@@ -810,8 +756,7 @@
         break;
       case CanvasResourceType::kBitmap:
         provider = std::make_unique<CanvasResourceProviderBitmap>(
-            size, filter_quality, color_params, context_provider_wrapper,
-            resource_dispatcher);
+            size, filter_quality, color_params, resource_dispatcher);
         break;
       case CanvasResourceType::kSharedImage: {
         if (!context_provider_wrapper)
@@ -872,6 +817,51 @@
   return nullptr;
 }
 
+std::unique_ptr<CanvasResourceProvider>
+CanvasResourceProvider::CreateBitmapProvider(
+    const IntSize& size,
+    SkFilterQuality filter_quality,
+    const CanvasColorParams& color_params) {
+  auto provider = std::make_unique<CanvasResourceProviderBitmap>(
+      size, filter_quality, color_params,
+      /*resource_dispatcher=*/nullptr);
+  if (provider->IsValid())
+    return provider;
+
+  return nullptr;
+}
+
+std::unique_ptr<CanvasResourceProvider>
+CanvasResourceProvider::CreateSharedImageProvider(
+    const IntSize& size,
+    base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
+    SkFilterQuality filter_quality,
+    const CanvasColorParams& color_params,
+    bool is_origin_top_left,
+    uint32_t shared_image_usage_flags) {
+  if (!context_provider_wrapper)
+    return nullptr;
+
+  const auto& caps =
+      context_provider_wrapper->ContextProvider()->GetCapabilities();
+  if (size.Width() > caps.max_texture_size ||
+      size.Height() > caps.max_texture_size) {
+    return nullptr;
+  }
+
+  if (!IsGMBAllowed(size, color_params, caps))
+    shared_image_usage_flags &= ~gpu::SHARED_IMAGE_USAGE_SCANOUT;
+
+  auto provider = std::make_unique<CanvasResourceProviderSharedImage>(
+      size, 0 /* msaa_sample_count */, filter_quality, color_params,
+      context_provider_wrapper, nullptr /*resource_dispatcher*/,
+      is_origin_top_left, true /* is_accelerated */, shared_image_usage_flags);
+  if (provider->IsValid())
+    return provider;
+
+  return nullptr;
+}
+
 class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider {
  public:
   CanvasImageProvider(cc::ImageDecodeCache* cache_n32,
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
index f6787de..3fcdfb2c 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -57,8 +57,9 @@
  public:
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
+  // todo(juanmihd@) ResourceUsage will be removed soon, try avoiding using this
   enum class ResourceUsage {
-    kSoftwareResourceUsage = 0,
+    kSoftwareResourceUsage = 0,  // deprecated
     kSoftwareCompositedResourceUsage = 1,
     kAcceleratedResourceUsage = 2,
     kAcceleratedCompositedResourceUsage = 3,
@@ -93,20 +94,22 @@
     kMaxValue = kSwapChain,
   };
 
-  void static RecordTypeToUMA(ResourceProviderType type);
-
-  // TODO(juanmihd): Clean up creation methods/usage. See crbug.com/1035589.
-  static std::unique_ptr<CanvasResourceProvider> CreateForCanvas(
+  // todo(juanmihd@) Check whether SkFilterQuality is needed in all of this, or
+  // just call setFilterQuality explicitly
+  static std::unique_ptr<CanvasResourceProvider> CreateBitmapProvider(
       const IntSize&,
-      ResourceUsage,
+      SkFilterQuality,
+      const CanvasColorParams&);
+
+  static std::unique_ptr<CanvasResourceProvider> CreateSharedImageProvider(
+      const IntSize&,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
-      unsigned msaa_sample_count,
       SkFilterQuality,
       const CanvasColorParams&,
-      uint8_t presentation_mode,
-      base::WeakPtr<CanvasResourceDispatcher>,
-      bool is_origin_top_left = true);
+      bool is_origin_top_left,
+      uint32_t shared_image_usage_flags);
 
+  // TODO(juanmihd): Clean up creation methods/usage. See crbug.com/1035589.
   static std::unique_ptr<CanvasResourceProvider> Create(
       const IntSize&,
       ResourceUsage,
@@ -118,13 +121,6 @@
       base::WeakPtr<CanvasResourceDispatcher>,
       bool is_origin_top_left = true);
 
-  static std::unique_ptr<CanvasResourceProvider> CreateAccelerated(
-      const IntSize&,
-      base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
-      const CanvasColorParams&,
-      bool is_origin_top_left,
-      uint32_t shared_image_usage_flags);
-
   // Use Snapshot() for capturing a frame that is intended to be displayed via
   // the compositor. Cases that are destined to be transferred via a
   // TransferableResource should call ProduceCanvasResource() instead.
@@ -212,6 +208,8 @@
 
   void RestoreBackBuffer(const cc::PaintImage&);
 
+  ResourceProviderType GetType() const { return type_; }
+
  protected:
   gpu::gles2::GLES2Interface* ContextGL() const;
   gpu::raster::RasterInterface* RasterInterface() const;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
index 8852771..e8fceaf 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -103,6 +103,7 @@
   EXPECT_TRUE(provider->IsSingleBuffered());
 }
 
+// TODO(juanmihd): Fix this test. See crbug.com/1035589.
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(
@@ -293,12 +294,8 @@
       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
       kNonOpaque);
 
-  auto provider = CanvasResourceProvider::Create(
-      kSize, CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
-      context_provider_wrapper_, 0 /* msaa_sample_count */,
-      kLow_SkFilterQuality, kColorParams,
-      CanvasResourceProvider::kAllowImageChromiumPresentationMode,
-      nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+  auto provider = CanvasResourceProvider::CreateBitmapProvider(
+      kSize, kLow_SkFilterQuality, kColorParams);
 
   EXPECT_EQ(provider->Size(), kSize);
   EXPECT_TRUE(provider->IsValid());
@@ -475,6 +472,7 @@
     SCOPED_TRACE(i);
     auto usage = static_cast<CanvasResourceProvider::ResourceUsage>(i);
     bool should_support_compositing = false;
+    std::unique_ptr<CanvasResourceProvider> provider;
     switch (usage) {
       case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
         should_support_compositing = false;
@@ -499,30 +497,51 @@
         break;
     }
 
-    auto provider = CanvasResourceProvider::Create(
-        IntSize(kMaxTextureSize - 1, kMaxTextureSize), usage,
-        context_provider_wrapper_, 0 /* msaa_sample_count */,
-        kLow_SkFilterQuality, kColorParams,
-        CanvasResourceProvider::kAllowImageChromiumPresentationMode,
-        nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+    if (usage ==
+        CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage) {
+      provider = CanvasResourceProvider::CreateBitmapProvider(
+          IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
+          kColorParams);
+    } else {
+      provider = CanvasResourceProvider::Create(
+          IntSize(kMaxTextureSize - 1, kMaxTextureSize), usage,
+          context_provider_wrapper_, 0 /* msaa_sample_count */,
+          kLow_SkFilterQuality, kColorParams,
+          CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+          nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+    }
     EXPECT_EQ(provider->SupportsDirectCompositing(),
               should_support_compositing);
 
-    provider = CanvasResourceProvider::Create(
-        IntSize(kMaxTextureSize, kMaxTextureSize), usage,
-        context_provider_wrapper_, 0 /* msaa_sample_count */,
-        kLow_SkFilterQuality, kColorParams,
-        CanvasResourceProvider::kAllowImageChromiumPresentationMode,
-        nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+    if (usage ==
+        CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage) {
+      provider = CanvasResourceProvider::CreateBitmapProvider(
+          IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
+          kColorParams);
+    } else {
+      provider = CanvasResourceProvider::Create(
+          IntSize(kMaxTextureSize, kMaxTextureSize), usage,
+          context_provider_wrapper_, 0 /* msaa_sample_count */,
+          kLow_SkFilterQuality, kColorParams,
+          CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+          nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+    }
     EXPECT_EQ(provider->SupportsDirectCompositing(),
               should_support_compositing);
 
-    provider = CanvasResourceProvider::Create(
-        IntSize(kMaxTextureSize + 1, kMaxTextureSize), usage,
-        context_provider_wrapper_, 0 /* msaa_sample_count */,
-        kLow_SkFilterQuality, kColorParams,
-        CanvasResourceProvider::kAllowImageChromiumPresentationMode,
-        nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+    if (usage ==
+        CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage) {
+      provider = CanvasResourceProvider::CreateBitmapProvider(
+          IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
+          kColorParams);
+    } else {
+      provider = CanvasResourceProvider::Create(
+          IntSize(kMaxTextureSize + 1, kMaxTextureSize), usage,
+          context_provider_wrapper_, 0 /* msaa_sample_count */,
+          kLow_SkFilterQuality, kColorParams,
+          CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+          nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+    }
     EXPECT_FALSE(provider->SupportsDirectCompositing());
   }
 }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c9e3e1fc..ac55bc20 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1902,6 +1902,9 @@
 # PLEASE DO NOT PUT ANYTHING INSIDE THIS SECTION!!
 # ======
 
+# -- Section 1
+# -- Section 1
+# -- Section 1
 crbug.com/1053725 [ Mac ] compositing/contents-opaque/control-layer.html [ Skip ]
 crbug.com/1053725 [ Mac ] compositing/gestures/gesture-tapHighlight-with-box-shadow.html [ Skip ]
 crbug.com/1053725 [ Mac ] compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html [ Skip ]
@@ -2104,6 +2107,11 @@
 crbug.com/1053725 [ Mac ] fast/css/text-overflow-ellipsis-button.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/css/text-overflow-input.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/css-grid-layout/preferred-width-computed-after-layout.html [ Skip ]
+
+# -- Section 2
+# -- Section 2
+# -- Section 2
+
 crbug.com/1053725 [ Mac ] fast/dom/52776.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/dom/focus-contenteditable.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/dom/HTMLMeterElement/meter-boundary-values.html [ Skip ]
@@ -2295,6 +2303,11 @@
 crbug.com/1053725 [ Mac ] fast/forms/select/select-writing-direction-natural.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/forms/select/selectlist-minsize.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/forms/submit/submit-appearance-basic.html [ Skip ]
+
+# -- Section 3
+# -- Section 3
+# -- Section 3
+
 crbug.com/1053725 [ Mac ] fast/forms/suggestion-picker/date-suggestion-picker-appearance-rtl.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/forms/suggestion-picker/date-suggestion-picker-appearance-with-scroll-bar.html [ Skip ]
 crbug.com/1053725 [ Mac ] fast/forms/suggestion-picker/date-suggestion-picker-appearance.html [ Skip ]
@@ -2486,6 +2499,11 @@
 crbug.com/1053725 [ Mac ] http/tests/devtools/editor/text-editor-mark-clean.js [ Skip ]
 crbug.com/1053725 [ Mac ] http/tests/devtools/editor/text-editor-smart-braces.js [ Skip ]
 crbug.com/1053725 [ Mac ] http/tests/devtools/editor/text-editor-token-at-position.js [ Skip ]
+
+# -- Section 4
+# -- Section 4
+# -- Section 4
+
 crbug.com/1053725 [ Mac ] http/tests/devtools/elements/breadcrumb-updates.js [ Skip ]
 crbug.com/1053725 [ Mac ] http/tests/devtools/elements/dom-search-crash.js [ Skip ]
 crbug.com/1053725 [ Mac ] http/tests/devtools/elements/elements-child-node-count-mismatch.js [ Skip ]
@@ -2668,6 +2686,11 @@
 crbug.com/1053725 [ Mac ] transforms/transformed-focused-text-input.html [ Skip ]
 crbug.com/1053725 [ Mac ] transforms/2d/zoom-menulist.html [ Skip ]
 crbug.com/1053725 [ Mac ] transforms/3d/general/perspective-non-layer.html [ Skip ]
+
+# -- Section 5
+# -- Section 5
+# -- Section 5
+
 crbug.com/1053725 [ Mac ] virtual/cascade/fast/forms/001.html [ Skip ]
 crbug.com/1053725 [ Mac ] virtual/cascade/fast/forms/button-style-color.html [ Skip ]
 crbug.com/1053725 [ Mac ] virtual/cascade/fast/forms/color/color-suggestion-picker-appearance.html [ Skip ]
@@ -7456,6 +7479,9 @@
 crbug.com/1049689 external/wpt/workers/modules/shared-worker-import-referrer.html [ Pass Timeout ]
 crbug.com/1049689 virtual/omt-worker-fetch/external/wpt/workers/modules/shared-worker-import-referrer.html [ Pass Timeout ]
 
+# Crashes with DCHECK enabled, but not on normal Release builds.
+crbug.com/944449 external/wpt/scroll-animations/scroll-animation.html [ Pass Crash ]
+
 # Sheriff 2020-02-10
 crbug.com/1050306 [ Fuchsia ] virtual/gpu/fast/canvas/canvas-filter-frameless-document.html [ Crash Pass Timeout ]
 
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
index 8e0cf8b..25dab77 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -37,6 +37,12 @@
      {}
     ]
    ],
+   "css/css-flexbox/padding-overflow-crash.html": [
+    [
+     "css/css-flexbox/padding-overflow-crash.html",
+     {}
+    ]
+   ],
    "css/css-flexbox/zero-content-size-with-scrollbar-crash.html": [
     [
      "css/css-flexbox/zero-content-size-with-scrollbar-crash.html",
@@ -132940,6 +132946,12 @@
    "content-security-policy/nonce-hiding/script-nonces-hidden.html.headers": [
     []
    ],
+   "content-security-policy/nonce-hiding/svgscript-nonces-hidden-expected.txt": [
+    []
+   ],
+   "content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub-expected.txt": [
+    []
+   ],
    "content-security-policy/nonce-hiding/svgscript-nonces-hidden.html.headers": [
     []
    ],
@@ -164215,9 +164227,6 @@
    "html/cross-origin-embedder-policy/require-corp-about-srcdoc.html.headers": [
     []
    ],
-   "html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https-expected.txt": [
-    []
-   ],
    "html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html.headers": [
     []
    ],
@@ -181108,9 +181117,6 @@
    "resize-observer/idlharness.window-expected.txt": [
     []
    ],
-   "resize-observer/observe-expected.txt": [
-    []
-   ],
    "resize-observer/resources/iframe.html": [
     []
    ],
@@ -181348,9 +181354,6 @@
    "resources/.htaccess": [
     []
    ],
-   "resources/LICENSE": [
-    []
-   ],
    "resources/META.yml": [
     []
    ],
@@ -182449,6 +182452,9 @@
    "service-workers/service-worker/fetch-error.https-expected.txt": [
     []
    ],
+   "service-workers/service-worker/fetch-event-handled.https-expected.txt": [
+    []
+   ],
    "service-workers/service-worker/fetch-event-is-reload-iframe-navigation-manual.https-expected.txt": [
     []
    ],
@@ -182818,6 +182824,9 @@
    "service-workers/service-worker/resources/fetch-event-async-respond-with-worker.js": [
     []
    ],
+   "service-workers/service-worker/resources/fetch-event-handled-worker.js": [
+    []
+   ],
    "service-workers/service-worker/resources/fetch-event-network-error-controllee-iframe.html": [
     []
    ],
@@ -183610,9 +183619,6 @@
    "shadow-dom/resources/shadow-dom.js": [
     []
    ],
-   "shadow-dom/untriaged/LICENSE": [
-    []
-   ],
    "shadow-dom/untriaged/README": [
     []
    ],
@@ -184606,6 +184612,12 @@
    "svg/pservers/parsing/stop-color-invalid-expected.txt": [
     []
    ],
+   "svg/pservers/reftests/gradient-inheritance-not-in-rendertree-01.tentative.svg": [
+    []
+   ],
+   "svg/pservers/reftests/gradient-inheritance-not-in-rendertree-02.tentative.svg": [
+    []
+   ],
    "svg/pservers/reftests/meshgradient-basic-001-ref.png": [
     []
    ],
@@ -184627,6 +184639,12 @@
    "svg/pservers/reftests/meshgradient-complex-001-ref.png": [
     []
    ],
+   "svg/pservers/reftests/pattern-inheritance-not-in-rendertree-01.tentative.svg": [
+    []
+   ],
+   "svg/pservers/reftests/pattern-inheritance-not-in-rendertree-02.tentative.svg": [
+    []
+   ],
    "svg/pservers/reftests/radialgradient-basic-002-ref.svg": [
     []
    ],
@@ -188326,9 +188344,6 @@
    "tools/wpt/wpt.py": [
     []
    ],
-   "tools/wptrunner/LICENSE": [
-    []
-   ],
    "tools/wptrunner/MANIFEST.in": [
     []
    ],
@@ -188683,9 +188698,6 @@
    "tools/wptrunner/wptrunner/wpttest.py": [
     []
    ],
-   "tools/wptserve/LICENSE": [
-    []
-   ],
    "tools/wptserve/MANIFEST.in": [
     []
    ],
@@ -189823,18 +189835,6 @@
    "wasm/webapi/empty-body.any.worker-expected.txt": [
     []
    ],
-   "wasm/webapi/invalid-code.any-expected.txt": [
-    []
-   ],
-   "wasm/webapi/invalid-code.any.serviceworker-expected.txt": [
-    []
-   ],
-   "wasm/webapi/invalid-code.any.sharedworker-expected.txt": [
-    []
-   ],
-   "wasm/webapi/invalid-code.any.worker-expected.txt": [
-    []
-   ],
    "wasm/webapi/status.py": [
     []
    ],
@@ -190015,15 +190015,9 @@
    "web-nfc/NDEFReader_scan_filter.https-expected.txt": [
     []
    ],
-   "web-nfc/NDEFRecord_constructor.https-expected.txt": [
-    []
-   ],
    "web-nfc/NDEFWriter-document-hidden-manual.https-expected.txt": [
     []
    ],
-   "web-nfc/NDEFWriter_write.https-expected.txt": [
-    []
-   ],
    "web-nfc/OWNERS": [
     []
    ],
@@ -295379,6 +295373,30 @@
      }
     ]
    ],
+   "performance-timeline/po-disconnect-removes-observed-types.any.js": [
+    [
+     "performance-timeline/po-disconnect-removes-observed-types.any.html",
+     {
+      "script_metadata": [
+       [
+        "script",
+        "performanceobservers.js"
+       ]
+      ]
+     }
+    ],
+    [
+     "performance-timeline/po-disconnect-removes-observed-types.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "script",
+        "performanceobservers.js"
+       ]
+      ]
+     }
+    ]
+   ],
    "performance-timeline/po-disconnect.any.js": [
     [
      "performance-timeline/po-disconnect.any.html",
@@ -295475,6 +295493,30 @@
      }
     ]
    ],
+   "performance-timeline/po-observe-repeated-type.any.js": [
+    [
+     "performance-timeline/po-observe-repeated-type.any.html",
+     {
+      "script_metadata": [
+       [
+        "script",
+        "performanceobservers.js"
+       ]
+      ]
+     }
+    ],
+    [
+     "performance-timeline/po-observe-repeated-type.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "script",
+        "performanceobservers.js"
+       ]
+      ]
+     }
+    ]
+   ],
    "performance-timeline/po-observe-type.any.js": [
     [
      "performance-timeline/po-observe-type.any.html",
@@ -340268,6 +340310,12 @@
      {}
     ]
    ],
+   "service-workers/service-worker/fetch-event-handled.https.html": [
+    [
+     "service-workers/service-worker/fetch-event-handled.https.html",
+     {}
+    ]
+   ],
    "service-workers/service-worker/fetch-event-network-error.https.html": [
     [
      "service-workers/service-worker/fetch-event-network-error.https.html",
@@ -392828,19 +392876,27 @@
    "testharness"
   ],
   "content-security-policy/nonce-hiding/script-nonces-hidden.html": [
-   "b32635ff65817d739bc2b7ff003211bce166db14",
+   "d9718d904c24326b86bd2853dcdfebe11d644da5",
    "testharness"
   ],
   "content-security-policy/nonce-hiding/script-nonces-hidden.html.headers": [
    "ad8d0b54f31d6d0682152f9f75f65c649c36a6a7",
    "support"
   ],
+  "content-security-policy/nonce-hiding/svgscript-nonces-hidden-expected.txt": [
+   "05dc3875a3edb55a567274c663df66cb113ee069",
+   "support"
+  ],
+  "content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub-expected.txt": [
+   "05dc3875a3edb55a567274c663df66cb113ee069",
+   "support"
+  ],
   "content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub.html": [
-   "0bdf2ab8f488b7c32acd95acaa2e0628add504b8",
+   "870fef316eae9ca2fc5ab1182f746cfa6487cb05",
    "testharness"
   ],
   "content-security-policy/nonce-hiding/svgscript-nonces-hidden.html": [
-   "d6e9379d4710b13d7ea47ba3d0e3c5cb5721899c",
+   "a50c75b34ca59fe51b57b55aec95d1fcddb84350",
    "testharness"
   ],
   "content-security-policy/nonce-hiding/svgscript-nonces-hidden.html.headers": [
@@ -423971,6 +424027,10 @@
    "682199815e03d214941a24b6a167d22ee852ced2",
    "reftest"
   ],
+  "css/css-flexbox/padding-overflow-crash.html": [
+   "fd0c333fabadb073b9977a63de6a8c5c3ed79042",
+   "crashtest"
+  ],
   "css/css-flexbox/parsing/flex-basis-computed-expected.txt": [
    "ad4db31aab50ed0fa932bd677480d491316daf70",
    "support"
@@ -476396,11 +476456,11 @@
    "testharness"
   ],
   "css/cssom/CSSStyleSheet-constructable-expected.txt": [
-   "04ebd04b481cd593c0d05a7405be31e464543a41",
+   "e0293076a4feaaecf600e71025082acd435b9f6f",
    "support"
   ],
   "css/cssom/CSSStyleSheet-constructable.html": [
-   "a5cbe3431e8193a77c6082c83294458e74ff9662",
+   "539075b47efc8599c3d9147f2e4b417783fb1df5",
    "testharness"
   ],
   "css/cssom/CSSStyleSheet.html": [
@@ -500215,10 +500275,6 @@
    "8df98474b589d070992677cb0134bd47bd0509c4",
    "support"
   ],
-  "html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https-expected.txt": [
-   "1e0c4408a08b78de5411831db4d371b36fd1735d",
-   "support"
-  ],
   "html/cross-origin-embedder-policy/require-corp-load-from-cache-storage.https.html": [
    "489230a776d0d5b81f30789a4263837a6798f964",
    "testharness"
@@ -538115,6 +538171,10 @@
    "8f1b09bc377120802401de1b247aa57db7414c68",
    "testharness"
   ],
+  "performance-timeline/po-disconnect-removes-observed-types.any.js": [
+   "cac97bea0755c1182956fdf94c98ee78ca40b017",
+   "testharness"
+  ],
   "performance-timeline/po-disconnect.any.js": [
    "5f5fb5aa43ba46268f8c355fdc93c6f1829968b4",
    "testharness"
@@ -538131,6 +538191,10 @@
    "0b205e094c75e10bc1b93ff966aea0fd23a586f8",
    "testharness"
   ],
+  "performance-timeline/po-observe-repeated-type.any.js": [
+   "2bba396a6b69ebad56ad4f1b135cb8ad49d321b7",
+   "testharness"
+  ],
   "performance-timeline/po-observe-type.any.js": [
    "2c0719a8d146882ad317ff2418e89d4e77a2da18",
    "testharness"
@@ -538768,7 +538832,7 @@
    "support"
   ],
   "portals/about-blank-cannot-host.html": [
-   "59858c690dcbfafaa673371384271d8b2a3c1a7c",
+   "6a721c32e6807cbd615b3adbffd7422467375525",
    "testharness"
   ],
   "portals/csp/frame-ancestors.sub.html": [
@@ -538776,7 +538840,7 @@
    "testharness"
   ],
   "portals/csp/frame-src.sub.html": [
-   "34f1474d4b37f6a867b858a0bfc88e03db48153a",
+   "1b37fd4ac2148e10828112876bb8ad0aaa818075",
    "testharness"
   ],
   "portals/csp/resources/frame-src.sub.html": [
@@ -538792,7 +538856,7 @@
    "testharness"
   ],
   "portals/history/history-manipulation-inside-portal.html": [
-   "d19e153e51cabedecd4e86ce457dd714e7eac82e",
+   "efbf1de136cca726701fc1827dd0a00fda93c987",
    "testharness"
   ],
   "portals/history/resources/inner-iframe.html": [
@@ -538816,7 +538880,7 @@
    "support"
   ],
   "portals/htmlportalelement-event-handler-content-attributes.html": [
-   "8fc26386cfc9d30e89062440b9347c62b60aa592",
+   "04b4615205ae9f036231370b9d30aa217608f2c4",
    "testharness"
   ],
   "portals/portal-activate-data-expected.txt": [
@@ -538824,7 +538888,7 @@
    "support"
   ],
   "portals/portal-activate-data.html": [
-   "9a712c914950eaa69d469c4218af8629f8ebe87a",
+   "cefb0eae3dc9a8b10880687fc084d44991f8f26f",
    "testharness"
   ],
   "portals/portal-activate-event-constructor.html": [
@@ -538832,19 +538896,19 @@
    "testharness"
   ],
   "portals/portal-activate-event.html": [
-   "780e8b58af98cc910e3739e3a9a2e5567d5613d0",
+   "990dc2d4b85ac3ca49e246ba17249a2986592e4d",
    "testharness"
   ],
   "portals/portal-non-http-navigation.html": [
-   "3b79df3c230e1128574d4a6eb81d407cd9303e2c",
+   "e2b5d3d3937e4991d99caa3d87901ffe6202a100",
    "testharness"
   ],
   "portals/portal-onload-event.html": [
-   "c9f07fcc889043cd523206728f7daaaefa653409",
+   "da770013e26506cca3a314e39f6deb962e42578f",
    "testharness"
   ],
   "portals/portals-activate-empty-browsing-context.html": [
-   "4beff610ea0d3da3d4d9133ceaa570f879e0c03b",
+   "d904cd58543ff02c280d3f43267b8d54cad7882b",
    "testharness"
   ],
   "portals/portals-activate-inside-iframe-expected.txt": [
@@ -538852,27 +538916,27 @@
    "support"
   ],
   "portals/portals-activate-inside-iframe.html": [
-   "4fbe9ba333b4e81e62a1b918c914d45617daf70d",
+   "5234babfdf9528c5b9d7861ba90ffe6ceebaccce",
    "testharness"
   ],
   "portals/portals-activate-inside-portal.html": [
-   "efeb23d4e38d21627be812fa85bbd5d74ba83da4",
+   "bd0d9e27bb6b25adbc3844adc8f8f947cf83dce1",
    "testharness"
   ],
   "portals/portals-activate-no-browsing-context.html": [
-   "cf5cb35da2fd7b9e5d6561fb58a63495de82f1c5",
+   "bfc45f68c1859401b015d9cd22aaf50cdefb1770",
    "testharness"
   ],
   "portals/portals-activate-resolution.html": [
-   "db77a990e532a3d1b88f57300094cbd60215d69d",
+   "ada8d4619a075df9c8c422c5d8ff54a0f9700deb",
    "testharness"
   ],
   "portals/portals-activate-twice.html": [
-   "731a342c7f58101cabd82f9a8f71e739ac31d217",
+   "eaef8b7cc94e0e62bc34e32d4c48c7b6bcb9f83d",
    "testharness"
   ],
   "portals/portals-adopt-predecessor.html": [
-   "96d0be9a401771759c0d0cc5a9785497f9bf3447",
+   "21893987e63839bbfb8a9d67e0f41e7502c88812",
    "testharness"
   ],
   "portals/portals-api.html": [
@@ -538880,19 +538944,19 @@
    "testharness"
   ],
   "portals/portals-cross-origin-load.sub.html": [
-   "e19a225de046ba01a1232fb0cb456b6a706f583a",
+   "be817b8a0aa44de1773f7c9448a572a15bec9866",
    "testharness"
   ],
   "portals/portals-focus.sub.html": [
-   "97b7579eb63694310aa4d34b656c7414e68bd7c2",
+   "54fcf3a3d4734f0a1a1f49462afbeba21a5a0644",
    "testharness"
   ],
   "portals/portals-host-exposure.sub.html": [
-   "36fc2b48c8d87e10a1cb533e19372de1a9251825",
+   "3ff88413691db6c64b1cdb7a23fe2191640d47c2",
    "testharness"
   ],
   "portals/portals-host-hidden-after-activation.html": [
-   "f51e54bd49c5c1a422dab6f249fc3ee1da87eb0d",
+   "571ec55810aa8e76c3dd977f774b3a1eeb835904",
    "testharness"
   ],
   "portals/portals-host-null.html": [
@@ -538900,15 +538964,15 @@
    "testharness"
   ],
   "portals/portals-host-post-message.sub.html": [
-   "5331da0d7c3f0887bc161b7c8bc53ffcf3f1ebda",
+   "8750dd43d011ccf48d40f9671bd02c8dd29047c1",
    "testharness"
   ],
   "portals/portals-navigate-after-adoption.html": [
-   "5ad30d7928a6c4eda0cbcb5afad9c29234b9a057",
+   "f403902031303f21b9019c159d63b39ba1ff00d1",
    "testharness"
   ],
   "portals/portals-nested.html": [
-   "9d8d09be9b104b7fa0c58f58c5b19d641db6c0eb",
+   "41d053bd48d11a9511168bf570e2d9d08bd78fdb",
    "testharness"
   ],
   "portals/portals-no-frame-crash.html": [
@@ -538916,11 +538980,11 @@
    "crashtest"
   ],
   "portals/portals-post-message.sub.html": [
-   "5eee95cce654b30ce8401026d314b320f6cb4e45",
+   "f3927a0c05ace4e9e811548d49f6e0114560abf6",
    "testharness"
   ],
   "portals/portals-referrer-inherit-header.html": [
-   "0207474f37dea658ed9edb4352bd4e0719465558",
+   "da908cb2c21ff0c7996d36b326f18f400ad8b6be",
    "testharness"
   ],
   "portals/portals-referrer-inherit-header.html.headers": [
@@ -538928,27 +538992,27 @@
    "support"
   ],
   "portals/portals-referrer-inherit-meta.html": [
-   "cf0493fb6224233396f6169b59641c866096a82d",
+   "eecb247973e838c6fc5e09f32180fe58c81a2727",
    "testharness"
   ],
   "portals/portals-referrer.html": [
-   "cb08f56def7dfecaf3f5ed83cd668ed7f3ab663a",
+   "b9abcdb80de70dd5ed8135617945d59bdbb35269",
    "testharness"
   ],
   "portals/portals-rendering.html": [
-   "0eae0ddfd6ef1e9de2251f50914a855f4142b9d5",
+   "229dacf4e69962e0cde95658a328ad666c0b487e",
    "reftest"
   ],
   "portals/portals-repeated-activate.html": [
-   "a3843dddb47b55d920b249b01f47199b1202bda6",
+   "bf8d8ad42641c4d775db4255087383007df07698",
    "testharness"
   ],
   "portals/portals-set-src-after-activate.html": [
-   "70a16436a67f254372be5f861d83d9e9b66f895f",
+   "f9728170858792aae99aebeffe507bc5c94b0e19",
    "testharness"
   ],
   "portals/predecessor-fires-unload.html": [
-   "381221222b59c0346dae48cc83d4985d155610c9",
+   "dce2afb8e6fde03c292456a7e960b52b8558c8ca",
    "testharness"
   ],
   "portals/references/portals-rendering.html": [
@@ -539096,7 +539160,7 @@
    "support"
   ],
   "portals/xfo/portals-xfo-deny.sub.html": [
-   "13c3f7f4d1fcdde9d2a744955bce6308805f1618",
+   "dde09c6e72bf9d2f0632aecbf6f8ca1cd0006436",
    "testharness"
   ],
   "portals/xfo/resources/xfo-deny.asis": [
@@ -574143,12 +574207,8 @@
    "d5888515d5a086733c103592042bfc637f217aa4",
    "testharness"
   ],
-  "resize-observer/observe-expected.txt": [
-   "8ca858b4732cc49afbb5c8b40b09fc1228943348",
-   "support"
-  ],
   "resize-observer/observe.html": [
-   "3b336837b3bbea08f21d5d5c9534dd638f29a24b",
+   "1ab5f786877cb6aa6ae85dd566db0f4e38f1c330",
    "testharness"
   ],
   "resize-observer/resources/iframe.html": [
@@ -574755,10 +574815,6 @@
    "fd46101ca0099e76a8ed5723515f6e1bd220aebb",
    "support"
   ],
-  "resources/LICENSE": [
-   "45896e6be2bd51f4b78e9703caefb9b672e10a55",
-   "support"
-  ],
   "resources/META.yml": [
    "64a240ccbe8116a06ec40fd03140e6bbee7a260f",
    "support"
@@ -575180,7 +575236,7 @@
    "support"
   ],
   "scroll-animations/scroll-animation.html": [
-   "7a6f87574403a03703e0f4fd148667a0d573218d",
+   "62e5bb854aa2cc7d564c258f58e05342ffb8b446",
    "testharness"
   ],
   "scroll-animations/setting-current-time.html": [
@@ -576979,6 +577035,14 @@
    "d9147f85494c21e54d39a4fd7af16efa1a126384",
    "testharness"
   ],
+  "service-workers/service-worker/fetch-event-handled.https-expected.txt": [
+   "42484619e33308d010376fec1eda99c0bdea03c3",
+   "support"
+  ],
+  "service-workers/service-worker/fetch-event-handled.https.html": [
+   "2d6f6c86d876daf40ea8f41be01bca2c549bcc41",
+   "testharness"
+  ],
   "service-workers/service-worker/fetch-event-is-history-backward-navigation-manual.https.html": [
    "3cf5922f396afe4fa4a4787917fe0ab3faa36f0d",
    "manual"
@@ -577915,6 +577979,10 @@
    "dc3f1a1e98563ad1b5924c8315c0d64d17ffbbfd",
    "support"
   ],
+  "service-workers/service-worker/resources/fetch-event-handled-worker.js": [
+   "4af58e20d05c902d74511579e6b74894731d1239",
+   "support"
+  ],
   "service-workers/service-worker/resources/fetch-event-network-error-controllee-iframe.html": [
    "f6c1919bbcf63a0f23f7ea4f0f8baa0e5bae4035",
    "support"
@@ -579423,10 +579491,6 @@
    "948d389298f46cc906fa998c8b495ad55bd50a1a",
    "testharness"
   ],
-  "shadow-dom/untriaged/LICENSE": [
-   "531fac43af201b503c333f845587f0cca88c9c5f",
-   "support"
-  ],
   "shadow-dom/untriaged/README": [
    "5b7572bda4e2c2b2477a151345de3441265a8ca8",
    "support"
@@ -583387,6 +583451,14 @@
    "04a453545f5938489eb111a23a16c8c89065ed4e",
    "testharness"
   ],
+  "svg/pservers/reftests/gradient-inheritance-not-in-rendertree-01.tentative.svg": [
+   "8f80b2d94456da9db42e9dee7dbf08d57d533088",
+   "support"
+  ],
+  "svg/pservers/reftests/gradient-inheritance-not-in-rendertree-02.tentative.svg": [
+   "5b230f1d31ce77f3c877eba49e24261fabc2a840",
+   "support"
+  ],
   "svg/pservers/reftests/meshgradient-basic-001-ref.png": [
    "691bff6244cd0abe046536efc0a100329b62d407",
    "support"
@@ -583443,6 +583515,14 @@
    "625fae59ea53c96080ce3105e247bda46e7ed4c8",
    "reftest"
   ],
+  "svg/pservers/reftests/pattern-inheritance-not-in-rendertree-01.tentative.svg": [
+   "1a6d0a0b32b69890417b27647e3de12c9d9b16af",
+   "support"
+  ],
+  "svg/pservers/reftests/pattern-inheritance-not-in-rendertree-02.tentative.svg": [
+   "961d069e0864d8379c44d81aea19aebfb6eca66a",
+   "support"
+  ],
   "svg/pservers/reftests/radialgradient-basic-002-ref.svg": [
    "26f4f508f35855ffd35baffb1aff129fe1ebf1be",
    "support"
@@ -588991,10 +589071,6 @@
    "49ee6345381450c4087423b2f7d1c9538f813c92",
    "support"
   ],
-  "tools/wptrunner/LICENSE": [
-   "45896e6be2bd51f4b78e9703caefb9b672e10a55",
-   "support"
-  ],
   "tools/wptrunner/MANIFEST.in": [
    "d36344f9668919f9dfc8f2e60a470a5d0484c292",
    "support"
@@ -589376,7 +589452,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/update/sync.py": [
-   "0d75a1232fc0cba9fbd6e8a3363adea0475dd436",
+   "0a41f706ebc3760729d9ba553076fe0d7e0b40b8",
    "support"
   ],
   "tools/wptrunner/wptrunner/update/tree.py": [
@@ -589467,10 +589543,6 @@
    "e8c267460661ae2978b2af2b903b494ad1a81c3a",
    "support"
   ],
-  "tools/wptserve/LICENSE": [
-   "45896e6be2bd51f4b78e9703caefb9b672e10a55",
-   "support"
-  ],
   "tools/wptserve/MANIFEST.in": [
    "4bf44835220d8d466be23757a194bdc92aaa5584",
    "support"
@@ -594951,26 +595023,10 @@
    "b27e018a984e398b6c001426abdf8cfdc641f782",
    "testharness"
   ],
-  "wasm/webapi/invalid-code.any-expected.txt": [
-   "90be5923681eb21512b039c910735bc0af4c8adb",
-   "support"
-  ],
   "wasm/webapi/invalid-code.any.js": [
-   "2b901ae0a63ade67bf7494cfc32d559f6d003104",
+   "752519392a953fdc314d6421f2bcb91856434534",
    "testharness"
   ],
-  "wasm/webapi/invalid-code.any.serviceworker-expected.txt": [
-   "90be5923681eb21512b039c910735bc0af4c8adb",
-   "support"
-  ],
-  "wasm/webapi/invalid-code.any.sharedworker-expected.txt": [
-   "90be5923681eb21512b039c910735bc0af4c8adb",
-   "support"
-  ],
-  "wasm/webapi/invalid-code.any.worker-expected.txt": [
-   "90be5923681eb21512b039c910735bc0af4c8adb",
-   "support"
-  ],
   "wasm/webapi/origin.sub.any.js": [
    "bf7901eeddee7c28413031198c4f138b7a23d6ea",
    "testharness"
@@ -595659,12 +595715,8 @@
    "122070f50ed7c4fdb15947cbec68e2a62eea9a06",
    "testharness"
   ],
-  "web-nfc/NDEFRecord_constructor.https-expected.txt": [
-   "6af67f3fc240e539ed7c1d4dafb4979783815851",
-   "support"
-  ],
   "web-nfc/NDEFRecord_constructor.https.html": [
-   "4772407baafb029cd10c09f6434fd71f703905a8",
+   "6d6b8117ef03fc8a1357e3eec4b10e39a9cc7dac",
    "testharness"
   ],
   "web-nfc/NDEFWriter-document-hidden-manual.https-expected.txt": [
@@ -595675,10 +595727,6 @@
    "1a2839857bb69fc06b6ea779e138b17cf54ca580",
    "manual"
   ],
-  "web-nfc/NDEFWriter_write.https-expected.txt": [
-   "1e96c806d815a2d94ee4d28fbfec82c1107e4937",
-   "support"
-  ],
   "web-nfc/NDEFWriter_write.https.html": [
    "1cca68c4a9676d7d988f6b46bbba0250ccae40bd",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/script-nonces-hidden.html b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/script-nonces-hidden.html
index b32635f..d9718d90 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/script-nonces-hidden.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/script-nonces-hidden.html
@@ -149,10 +149,10 @@
 <nonce-element nonce="abc"></nonce-element>
 <script nonce="abc">
   test(t => {
+    assert_object_equals(eventList[0], { type: "AttributeChanged", name: "nonce", oldValue: null, newValue: "abc" }, "AttributeChanged 1");
+    assert_object_equals(eventList[1], { type: "Connected" }, "Connected");
+    assert_object_equals(eventList[2], { type: "AttributeChanged", name: "nonce", oldValue: "abc", newValue: "" }, "AttributeChanged 2");
     assert_equals(eventList.length, 3);
-    assert_object_equals(eventList[0], { type: "AttributeChanged", name: "nonce", oldValue: null, newValue: "abc" });
-    assert_object_equals(eventList[1], { type: "Connected" });
-    assert_object_equals(eventList[2], { type: "AttributeChanged", name: "nonce", oldValue: "abc", newValue: "" });
   }, "Custom elements expose the correct events.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-expected.txt
new file mode 100644
index 0000000..05dc387
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+PASS Reading 'nonce' content attribute and IDL attribute.
+PASS Cloned node retains nonce.
+PASS Cloned node retains nonce when inserted.
+FAIL Writing 'nonce' content attribute. assert_equals: expected "foo" but got "abc"
+PASS Writing 'nonce' IDL attribute.
+PASS Document-written script executes.
+PASS Document-written script's nonce value.
+PASS createElement.nonce.
+PASS createElement.setAttribute.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub-expected.txt
new file mode 100644
index 0000000..05dc387
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+PASS Reading 'nonce' content attribute and IDL attribute.
+PASS Cloned node retains nonce.
+PASS Cloned node retains nonce when inserted.
+FAIL Writing 'nonce' content attribute. assert_equals: expected "foo" but got "abc"
+PASS Writing 'nonce' IDL attribute.
+PASS Document-written script executes.
+PASS Document-written script's nonce value.
+PASS createElement.nonce.
+PASS createElement.setAttribute.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub.html b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub.html
index 0bdf2ab..870fef3 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.sub.html
@@ -49,7 +49,7 @@
     test(t => {
       script.setAttribute('nonce', 'foo');
       assert_equals(script.getAttribute('nonce'), 'foo');
-      assert_equals(script.nonce, 'abc');
+      assert_equals(script.nonce, 'foo');
     }, "Writing 'nonce' content attribute.");
 
     // Set the IDL attribute to 'bar'
@@ -77,6 +77,8 @@
       innerScript.innerText = script.innerText;
       innerScript.nonce = 'abc';
       s.appendChild(innerScript);
+      assert_equals(innerScript.nonce, 'abc');
+      assert_equals(innerScript.getAttribute('nonce'), null, 'innerScript.getAttribute nonce');
       document.body.appendChild(s);
       assert_equals(innerScript.nonce, 'abc');
       assert_equals(innerScript.getAttribute('nonce'), null, 'innerScript.getAttribute nonce');
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden.html b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden.html
index d6e9379..a50c75b 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/svgscript-nonces-hidden.html
@@ -49,7 +49,7 @@
     test(t => {
       script.setAttribute('nonce', 'foo');
       assert_equals(script.getAttribute('nonce'), 'foo');
-      assert_equals(script.nonce, 'abc');
+      assert_equals(script.nonce, 'foo');
     }, "Writing 'nonce' content attribute.");
 
     // Set the IDL attribute to 'bar'
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt
index 04ebd04..e029307 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable-expected.txt
@@ -21,7 +21,7 @@
 PASS Inserting an @import rule through insertRule on a constructed stylesheet throws an exception
 PASS CSSStyleSheet.replaceSync should not trigger any loads from @import rules
 PASS CSSStyleSheet.replace allows import rule inside
-PASS CSSStyleSheet.replace returns rejected promise on failed imports
+FAIL CSSStyleSheet.replace returns rejected promise on failed imports assert_equals: expected "NetworkError" but got "NotAllowedError"
 PASS Cloning a shadow host will not clone shadow root, and also adoptedStyleSheets
 PASS Importing a shadow host will not copy shadow root, and also adoptedStyleSheets
 PASS Adopting a shadow host will empty adoptedStyleSheets if adopting to a different document
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
index a5cbe343..539075b 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
@@ -120,7 +120,7 @@
   const greenSheet = new CSSStyleSheet();
   const redSheet = new CSSStyleSheet({media: "screen, print"});
   const blueSheet = new CSSStyleSheet({title: "Blue", disabled: true});
-  const whiteSheet = new CSSStyleSheet({title: "White", alternate: true});
+  const whiteSheet = new CSSStyleSheet({title: "White", disabled: true});
   const yellowSheet = new CSSStyleSheet({disabled: false});
 
   const greenPromise = greenSheet.replace(greenStyleText);
@@ -140,16 +140,17 @@
     const yellowStyleSheet = values[4];
 
     // Lists of style sheets can be created, assigned and read.
+
+    // disabled stylesheets aren't applied
     document.adoptedStyleSheets = [whiteStyleSheet];
-    // alternate stylesheets aren't applied when title != current preferable name
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
 
+    // disable dsheets don't block other styles from applying
     document.adoptedStyleSheets = [greenStyleSheet, blueStyleSheet];
-    // disabled stylesheets aren't applied
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 128, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
@@ -170,6 +171,7 @@
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(yellowSpan).color, "rgb(255, 255, 0)");
+    document.adoptedStyleSheets = [];
   });
 }, 'Constructed style sheets can be applied on document');
 
@@ -241,7 +243,6 @@
 }, 'Attaching a shadow root that already has adopted stylesheets work');
 
 test(() => {
-
   const sheet = new CSSStyleSheet();
   sheet.replaceSync(":host([red]) { color: red; } :host(.blue) { color: blue; }");
   const host = document.createElement("div");
@@ -327,7 +328,8 @@
     assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
-});
+    document.adoptedStyleSheets = [];
+  });
 }, 'Constructed stylesheet can be used and modified in multiple TreeScopes');
 
 promise_test(() => {
@@ -371,9 +373,11 @@
   });
 }, 'Stylesheets constructed on the main Document cannot be used in iframes');
 
-promise_test(() => {
+promise_test(async () => {
   const iframe = document.createElement("iframe");
+  const iframeLoaded = new Promise(resolve => iframe.addEventListener("load", resolve));
   document.body.appendChild(iframe);
+  await iframeLoaded;
   const thirdDiv = firstDiv.cloneNode(true);
   iframe.contentDocument.body.appendChild(thirdDiv);
   const greenIframeSpan = thirdDiv.children[0];
@@ -629,14 +633,19 @@
     assert_equals(sheet.cssRules.length, 1);
     assert_equals(sheet.cssRules[0].cssText, import_text);
     assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
+  }).catch((reason) => {
+    assert_unreached(`Promise was rejected (${reason}) when it should have been resolved`);
   });
 }, 'CSSStyleSheet.replace allows import rule inside');
 
 promise_test(() => {
   const sheet = new CSSStyleSheet();
-  const sheet_promise = sheet.replace("import url('not-there.css');");
-  return sheet_promise.catch((reason) => {
-    assert_equals(reason.name, "NotAllowedError");
+  const sheet_promise = sheet.replace("@import url('not-there.css');");
+
+  return sheet_promise.then((sheet) => {
+    assert_unreached("Promise was resolved when it should have been rejected");
+  }).catch((reason) => {
+    assert_equals(reason.name, "NetworkError");
   });
 }, 'CSSStyleSheet.replace returns rejected promise on failed imports');
 
diff --git a/third_party/blink/web_tests/external/wpt/portals/about-blank-cannot-host.html b/third_party/blink/web_tests/external/wpt/portals/about-blank-cannot-host.html
index 59858c6..6a721c3 100644
--- a/third_party/blink/web_tests/external/wpt/portals/about-blank-cannot-host.html
+++ b/third_party/blink/web_tests/external/wpt/portals/about-blank-cannot-host.html
@@ -4,6 +4,7 @@
 <script>
 
 promise_test(async (t) => {
+  assert_precondition("HTMLPortalElement" in self);
   let hostWindow = window.open();
   assert_equals(hostWindow.location.href, "about:blank");
 
diff --git a/third_party/blink/web_tests/external/wpt/portals/csp/frame-src.sub.html b/third_party/blink/web_tests/external/wpt/portals/csp/frame-src.sub.html
index 34f1474..1b37fd4 100644
--- a/third_party/blink/web_tests/external/wpt/portals/csp/frame-src.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/csp/frame-src.sub.html
@@ -6,6 +6,7 @@
 </body>
 <script>
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open("resources/frame-src.sub.html?frame_src_policy=%27none%27");
     w.onload = function() {
       w.document.addEventListener("securitypolicyviolation",
@@ -20,6 +21,7 @@
   }, "Tests that a portal can't be loaded when it violates frame-src");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open(`resources/frame-src.sub.html?frame_src_policy=http://{{hosts[][www]}}:{{ports[http][0]}}`);
     w.onload = function() {
       w.document.onsecuritypolicyviolation = t.unreached_func("Portal should load.");
@@ -30,7 +32,7 @@
     }
   }, "Tests that a portal can be loaded when the origin matches the frame-src CSP header.");
   async_test(function(t) {
-
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open(`resources/frame-src.sub.html?frame_src_policy=http://{{hosts[][www]}}:{{ports[http][0]}}`);
     w.onload = function() {
       var portal = w.document.createElement("portal");
diff --git a/third_party/blink/web_tests/external/wpt/portals/history/history-manipulation-inside-portal.html b/third_party/blink/web_tests/external/wpt/portals/history/history-manipulation-inside-portal.html
index d19e153e..efbf1de1 100644
--- a/third_party/blink/web_tests/external/wpt/portals/history/history-manipulation-inside-portal.html
+++ b/third_party/blink/web_tests/external/wpt/portals/history/history-manipulation-inside-portal.html
@@ -16,36 +16,42 @@
   }
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testHistoryPushStateInPortal');
     assertInitialHistoryState();
   }, 'history.pushState navigates independently with replacement in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testHistoryReplaceStateInPortal');
     assertInitialHistoryState();
   }, 'history.replaceState navigates independently in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testLocationAssignInPortal');
     assertInitialHistoryState();
   }, 'location.assign navigates independently with replacement in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testLocationReplaceInPortal');
     assertInitialHistoryState();
   }, 'location.replace navigates independently in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testSetLocationHrefInPortal');
     assertInitialHistoryState();
   }, 'Setting location.href navigates independently with replacement in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testSyntheticAnchorClickInPortal');
     assertInitialHistoryState();
diff --git a/third_party/blink/web_tests/external/wpt/portals/htmlportalelement-event-handler-content-attributes.html b/third_party/blink/web_tests/external/wpt/portals/htmlportalelement-event-handler-content-attributes.html
index 8fc26386..04b4615 100644
--- a/third_party/blink/web_tests/external/wpt/portals/htmlportalelement-event-handler-content-attributes.html
+++ b/third_party/blink/web_tests/external/wpt/portals/htmlportalelement-event-handler-content-attributes.html
@@ -7,6 +7,7 @@
 let eventNames = ["load", "message", "messageerror"];
 test(() => {
   try {
+    assert_precondition("HTMLPortalElement" in self);
     let portal = document.createElement("portal");
     for (let eventName of eventNames) {
       window.testValue = "not fired";
diff --git a/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html b/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html
index 9a712c9..cefb0eae 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html
@@ -13,6 +13,7 @@
 }
 
 async function openPortalAndActivate(logic, activateOptions) {
+  assert_precondition("HTMLPortalElement" in self);
   const w = await openBlankPortalHost();
   try {
     const portal = w.document.createElement('portal');
diff --git a/third_party/blink/web_tests/external/wpt/portals/portal-activate-event.html b/third_party/blink/web_tests/external/wpt/portals/portal-activate-event.html
index 780e8b58..990dc2d4 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portal-activate-event.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portal-activate-event.html
@@ -4,6 +4,7 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     let test = "eventlistener";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
@@ -15,6 +16,7 @@
   }, "Tests that the PortalActivateEvent is dispatched when a portal is activated.");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     let test = "eventhandler";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
@@ -26,6 +28,7 @@
   }, "Tests that the portalactivate event handler is dispatched when a portal is activated.");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     let test = "bodyeventhandler";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portal-non-http-navigation.html b/third_party/blink/web_tests/external/wpt/portals/portal-non-http-navigation.html
index 3b79df3..e2b5d3d 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portal-non-http-navigation.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portal-non-http-navigation.html
@@ -5,6 +5,7 @@
 <body>
 <script>
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement("portal");
   portal.src = "data:text/html,empty portal";
   portal.onload = t.unreached_func("Portal loaded data URL.");
@@ -13,6 +14,7 @@
 }, "Tests that a portal can't navigate to a data URL.");
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement("portal");
   portal.src = "about:blank";
   portal.onload = t.unreached_func("Portal loaded about:blank.");
@@ -21,6 +23,7 @@
 }, "Tests that a portal can't navigate to about:blank.");
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement("portal");
   portal.src = "resources/simple-portal.html";
   portal.onload = t.step_func(() => {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portal-onload-event.html b/third_party/blink/web_tests/external/wpt/portals/portal-onload-event.html
index c9f07fcc..da770013e 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portal-onload-event.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portal-onload-event.html
@@ -4,6 +4,7 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open("resources/simple-portal.html");
     w.onload = function() {
       var portal = w.document.createElement("portal");
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-activate-empty-browsing-context.html b/third_party/blink/web_tests/external/wpt/portals/portals-activate-empty-browsing-context.html
index 4beff61..d904cd5 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-activate-empty-browsing-context.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-activate-empty-browsing-context.html
@@ -4,6 +4,7 @@
 <body>
 <script>
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let portal = document.createElement('portal');
   document.body.appendChild(portal);
   t.add_cleanup(() => { document.body.removeChild(portal); });
@@ -12,6 +13,7 @@
 }, "A portal that has never been navigated cannot be activated");
 
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let portal = document.createElement('portal');
   document.body.appendChild(portal);
   t.add_cleanup(() => { document.body.removeChild(portal); });
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-iframe.html b/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-iframe.html
index 4fbe9ba3..5234babf 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-iframe.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-iframe.html
@@ -4,6 +4,7 @@
 <body>
   <script>
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       var iframe = document.createElement("iframe");
       iframe.src = "resources/portal-inside-iframe.html"
       var waitForLoad = new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-portal.html b/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-portal.html
index efeb23d..bd0d9e2 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-portal.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-activate-inside-portal.html
@@ -4,6 +4,7 @@
 <body>
   <script>
     promise_test(async () => {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = "resources/portal-activate-inside-portal.html";
       let waitForMessage = new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-activate-no-browsing-context.html b/third_party/blink/web_tests/external/wpt/portals/portals-activate-no-browsing-context.html
index cf5cb35..bfc45f6 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-activate-no-browsing-context.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-activate-no-browsing-context.html
@@ -3,6 +3,7 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let activatePromise = document.createElement('portal').activate();
   await promise_rejects_dom(t, 'InvalidStateError', activatePromise);
 }, "A portal with nothing in it cannot be activated");
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-activate-resolution.html b/third_party/blink/web_tests/external/wpt/portals/portals-activate-resolution.html
index db77a99..ada8d46 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-activate-resolution.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-activate-resolution.html
@@ -4,6 +4,7 @@
 <script src="resources/open-blank-host.js"></script>
 <script>
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var win = await openBlankPortalHost();
     var portal = win.document.createElement("portal");
     portal.src = new URL("resources/simple-portal.html", location.href)
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-activate-twice.html b/third_party/blink/web_tests/external/wpt/portals/portals-activate-twice.html
index 731a342..eaef8b7 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-activate-twice.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-activate-twice.html
@@ -3,6 +3,7 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let waitForMessage = new Promise((resolve, reject) => {
     window.onmessage = e => resolve(e.data);
   });
@@ -12,6 +13,7 @@
 }, "Calling activate when a portal is already activating should fail");
 
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let waitForMessage = new Promise((resolve, reject) => {
     window.onmessage = e => resolve(e.data);
   });
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-adopt-predecessor.html b/third_party/blink/web_tests/external/wpt/portals/portals-adopt-predecessor.html
index 96d0be9..21893987 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-adopt-predecessor.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-adopt-predecessor.html
@@ -13,6 +13,7 @@
   }
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-once";
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
     var message = await waitForCompletion(test);
@@ -20,6 +21,7 @@
   }, "Tests that a portal can adopt its predecessor.");
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-twice";
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
     var message = await waitForCompletion(test);
@@ -27,6 +29,7 @@
   }, "Tests that trying to adopt the predecessor twice will throw an exception.");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-after-event";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
@@ -37,6 +40,7 @@
   }, "Tests that trying to adopt the predecessor after the PortalActivateEvent will throw an exception.");
 
   promise_test(async t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-and-activate";
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
     var message = await waitForCompletion(test);
@@ -44,6 +48,7 @@
   }, "Tests that activating an adopted predecessor without inserting it works");
 
   async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-attach-remove";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
@@ -54,6 +59,7 @@
   }, "Tests that an adopting, inserting and then removing a predecessor works correctly");
 
   async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-and-discard";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
@@ -64,6 +70,7 @@
   }, "Tests that the adopted predecessor is destroyed if it isn't inserted");
 
   async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-to-disconnected-node";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-cross-origin-load.sub.html b/third_party/blink/web_tests/external/wpt/portals/portals-cross-origin-load.sub.html
index e19a225d..be817b8 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-cross-origin-load.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-cross-origin-load.sub.html
@@ -4,6 +4,7 @@
 <body>
 <script>
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var portal = document.createElement("portal");
     portal.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/simple-portal.html";
     return new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-focus.sub.html b/third_party/blink/web_tests/external/wpt/portals/portals-focus.sub.html
index 97b7579..54fcf3a 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-focus.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-focus.sub.html
@@ -8,6 +8,7 @@
 <body>
 <script>
   async function createPortal(doc, url) {
+    assert_precondition("HTMLPortalElement" in self);
     let portal = doc.createElement("portal");
     portal.src = url;
     doc.body.appendChild(portal);
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-host-exposure.sub.html b/third_party/blink/web_tests/external/wpt/portals/portals-host-exposure.sub.html
index 36fc2b4..3ff8841 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-host-exposure.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-host-exposure.sub.html
@@ -4,6 +4,7 @@
 <body>
 <script>
   function openPortalAndReceiveMessage(portalSrc) {
+    assert_precondition("HTMLPortalElement" in self);
     let portal = document.createElement('portal');
     portal.src = portalSrc;
     let received = new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-host-hidden-after-activation.html b/third_party/blink/web_tests/external/wpt/portals/portals-host-hidden-after-activation.html
index f51e54b..571ec55 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-host-hidden-after-activation.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-host-hidden-after-activation.html
@@ -19,6 +19,7 @@
   }
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     const portalUrl = encodeURIComponent("portal-host-hidden-after-activation-portal.html");
     window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
     var results = await waitForMessages();
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html b/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html
index 5331da0d..8750dd4 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html
@@ -17,6 +17,7 @@
     }
 
     async function createPortalAndLoopMessage(portalSrc, params) {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = await createPortal(portalSrc);
       var waitForResponse = new Promise((resolve, reject) => {
         portal.addEventListener("message", e => { resolve(e); });
@@ -72,6 +73,7 @@
     }, "postMessage with object message");
 
     promise_test(async () => {
+      assert_precondition("HTMLPortalElement" in self);
       function checkPort(port) {
         return new Promise((resolve, reject) => {
           var channel = new MessageChannel();
@@ -136,6 +138,7 @@
     }, "postMessage with invalid transferable should throw error");
 
     promise_test(async () => {
+      assert_precondition("HTMLPortalElement" in self);
        var receiveMessage = new Promise((resolve, reject) => {
          var bc = new BroadcastChannel("portal-host-post-message-after-activate");
          bc.onmessage = e => { resolve(e); };
@@ -148,6 +151,7 @@
     }, "Calling postMessage after receiving onactivate event should fail");
 
     promise_test(() => {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = "resources/portal-host-post-message-navigate-1.html";
       var count = 0;
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-navigate-after-adoption.html b/third_party/blink/web_tests/external/wpt/portals/portals-navigate-after-adoption.html
index 5ad30d7..f4039020 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-navigate-after-adoption.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-navigate-after-adoption.html
@@ -27,6 +27,7 @@
 }
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   let messageFromNewSrc = await openPortalAndActivate(
       'let predecessor = event.adoptPredecessor();' +
       'let readyPromise = new Promise((resolve, reject) => {' +
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-nested.html b/third_party/blink/web_tests/external/wpt/portals/portals-nested.html
index 9d8d09b..41d053bd 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-nested.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-nested.html
@@ -4,6 +4,7 @@
 <body>
   <script>
     promise_test(() => {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = "resources/portals-nested-portal.html";
       document.body.appendChild(portal);
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-post-message.sub.html b/third_party/blink/web_tests/external/wpt/portals/portals-post-message.sub.html
index 5eee95c..f3927a0 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-post-message.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-post-message.sub.html
@@ -12,6 +12,7 @@
     const crossOriginUrl = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-post-message-portal.html"
 
     async function createAndInsertPortal(portalSrc) {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = portalSrc;
       document.body.append(portal);
@@ -184,6 +185,7 @@
     }
 
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       window.open("resources/portal-post-message-before-activate-window.html");
       let {postMessageTS, activateTS} = await waitForMessage(
           "portals-post-message-before-activate");
@@ -191,12 +193,14 @@
     }, "postMessage before activate should work and preserve order");
 
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       window.open("resources/portal-post-message-during-activate-window.html");
       let error = await waitForMessage("portals-post-message-during-activate");
       assert_equals(error, "InvalidStateError");
     }, "postMessage during activate throws error");
 
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       window.open("resources/portal-post-message-after-activate-window.html");
       let error = await waitForMessage("portals-post-message-after-activate");
       assert_equals(error, "InvalidStateError");
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-header.html b/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-header.html
index 0207474f..da908cb 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-header.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-header.html
@@ -4,7 +4,7 @@
 <body>
 <script>
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-meta.html b/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-meta.html
index cf0493fb..eecb247 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-meta.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-referrer-inherit-meta.html
@@ -5,7 +5,7 @@
 <body>
 <script>
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-referrer.html b/third_party/blink/web_tests/external/wpt/portals/portals-referrer.html
index cb08f56d..b9abcdb8 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-referrer.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-referrer.html
@@ -4,7 +4,7 @@
 <body>
 <script>
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
@@ -21,7 +21,7 @@
 }, "portal contents should be loaded with referrer");
 
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   portal.referrerPolicy = 'no-referrer';
   let referrerPromise = new Promise((resolve, reject) => {
@@ -39,7 +39,7 @@
 }, "portal contents should be loaded with no referrer if referrerpolicy=no-referrer");
 
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   portal.referrerPolicy = 'origin';
   let referrerPromise = new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-rendering.html b/third_party/blink/web_tests/external/wpt/portals/portals-rendering.html
index 0eae0dd..229dacf4 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-rendering.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-rendering.html
@@ -2,16 +2,21 @@
 <html class="reftest-wait">
 <title>Portals rendering test</title>
 <link rel="match" href="references/portals-rendering.html">
-<body>
-  <script>
-    var portal = document.createElement('portal');
-    portal.src = 'resources/portals-rendering-portal.html';
-    portal.style = 'background-color: red; width: 100px; height: 100px';
-    portal.onmessage = e => {
-      window.requestAnimationFrame(function(ts) {
-        document.documentElement.classList.remove('reftest-wait');
-      });
-    }
-    document.body.appendChild(portal);
-  </script>
-</body>
+<body></body>
+<script>
+if (!("HTMLPortalElement" in self)) {
+  document.body.textContent = "PRECONDITION FAILED";
+  document.documentElement.classList.remove('reftest-wait');
+} else {
+  var portal = document.createElement('portal');
+  portal.src = 'resources/portals-rendering-portal.html';
+  portal.style = 'background-color: red; width: 100px; height: 100px';
+  portal.onmessage = e => {
+    window.requestAnimationFrame(function(ts) {
+      document.documentElement.classList.remove('reftest-wait');
+    });
+  };
+  document.body.appendChild(portal);
+}
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-repeated-activate.html b/third_party/blink/web_tests/external/wpt/portals/portals-repeated-activate.html
index a3843ddd..bf8d8ad 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-repeated-activate.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-repeated-activate.html
@@ -2,7 +2,8 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-  async_test(async t => {
+  async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     let win = window.open("resources/portal-repeated-activate-window.html");
     win.onload = () => win.activate();
     window.onmessage = t.step_func_done(() => {});
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-set-src-after-activate.html b/third_party/blink/web_tests/external/wpt/portals/portals-set-src-after-activate.html
index 70a1643..f972817 100644
--- a/third_party/blink/web_tests/external/wpt/portals/portals-set-src-after-activate.html
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-set-src-after-activate.html
@@ -10,6 +10,7 @@
 }
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   const w = await openBlankPortalHost();
   try {
     const portal = w.document.createElement('portal');
diff --git a/third_party/blink/web_tests/external/wpt/portals/predecessor-fires-unload.html b/third_party/blink/web_tests/external/wpt/portals/predecessor-fires-unload.html
index 3812212..dce2afb8 100644
--- a/third_party/blink/web_tests/external/wpt/portals/predecessor-fires-unload.html
+++ b/third_party/blink/web_tests/external/wpt/portals/predecessor-fires-unload.html
@@ -12,6 +12,7 @@
 }
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   const w = await openBlankPortalHost();
   try {
     const portal = w.document.createElement('portal');
@@ -29,6 +30,7 @@
 }, "pagehide and unload should fire if the predecessor is not adopted");
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   localStorage.setItem('predecessor-fires-unload-events', '');
   window.open('resources/predecessor-fires-unload-watch-unload.html', '_blank', 'noopener');
   while (localStorage.getItem('predecessor-fires-unload-events') != 'pagehide unload') {
diff --git a/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-deny.sub.html b/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-deny.sub.html
index 13c3f7f..dde09c6e 100644
--- a/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-deny.sub.html
+++ b/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-deny.sub.html
@@ -8,6 +8,7 @@
 // completion event.
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement('portal');
   portal.src = "/portals/xfo/resources/xfo-deny.asis";
   portal.onmessage = t.unreached_func("should not have received a message");
@@ -17,6 +18,7 @@
 }, "`XFO: DENY` blocks same-origin portals.");
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement('portal');
   portal.src = "http://{{domains[www]}}:{{ports[http][0]}}/portals/xfo/resources/xfo-deny.asis";
   portal.onmessage = t.unreached_func("should not have received a message");
diff --git a/third_party/blink/web_tests/external/wpt/resources/LICENSE b/third_party/blink/web_tests/external/wpt/resources/LICENSE
deleted file mode 100644
index 45896e6..0000000
--- a/third_party/blink/web_tests/external/wpt/resources/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-W3C 3-clause BSD License
-
-http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of works must retain the original copyright notice,
-  this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the original copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
-
-* Neither the name of the W3C nor the names of its contributors may be
-  used to endorse or promote products derived from this work without
-  specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation.html
index 7a6f8757..62e5bb8 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation.html
+++ b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation.html
@@ -135,4 +135,28 @@
       "The start time is zero in Playing state.");
 }, 'Animation start and current times are correct when multiple animations' +
     ' are attached to the same timeline.');
+
+promise_test(async t => {
+    const animation = createScrollLinkedAnimation(t);
+    const scroller = animation.timeline.scrollSource;
+    // Make the scroll timeline inactive.
+    scroller.style.overflow = "visible";
+    // Trigger layout;
+    scroller.scrollTop;
+    assert_equals(animation.timeline.currentTime, null,
+      "Timeline current time is null in inactive state.");
+    // Play the animation when the timeline is inactive.
+    animation.play();
+    // Make the scroll timeline active.
+    scroller.style.overflow = "auto";
+    await animation.ready;
+    // Ready promise is resolved as a result of the timeline becoming active.
+    assert_equals(animation.timeline.currentTime, 0,
+      "Timeline current time is resolved in active state.");
+    assert_equals(animation.currentTime, 0,
+      "Animation current time is resolved when the animation is ready.");
+    assert_equals(animation.startTime, 0,
+      "Animation start time is resolved when the animation is ready.");
+}, 'Animation start and current times are correct if scroll timeline is ' +
+   'activated after animation.play call.');
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt
new file mode 100644
index 0000000..42484619
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+PASS global setup
+FAIL FetchEvent.handled should resolve when respondWith() is not called assert_equals: expected "RESOLVED" but got "FAILED"
+FAIL FetchEvent.handled should reject when respondWith() is not called and the event is canceled assert_equals: expected "REJECTED" but got "FAILED"
+FAIL FetchEvent.handled should resolve when the promise provided to respondWith() is resolved assert_equals: expected "RESOLVED" but got "FAILED"
+FAIL FetchEvent.handled should reject when the promise provided to respondWith() is resolved to an invalid response assert_equals: expected "REJECTED" but got "FAILED"
+FAIL FetchEvent.handled should reject when the promise provided to respondWith() is rejected assert_equals: expected "REJECTED" but got "FAILED"
+PASS global cleanup
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html
new file mode 100644
index 0000000..2d6f6c86
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<title>Service Worker: FetchEvent.handled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+
+let frame = null;
+let worker = null;
+const script = 'resources/fetch-event-handled-worker.js';
+const scope = 'resources/simple.html';
+
+// Wait for a message from the service worker and removes the message handler.
+function wait_for_message_from_worker() {
+  return new Promise((resolve) => {
+    const handler = (event) => {
+      frame.contentWindow.navigator.serviceWorker.removeEventListener(
+          'message', handler);
+      resolve(event.data);
+    };
+    frame.contentWindow.navigator.serviceWorker.addEventListener(
+        'message', handler);
+  });
+}
+
+// Global setup: this must be the first promise_test.
+promise_test(async (t) => {
+  const registration =
+      await service_worker_unregister_and_register(t, script, scope);
+  worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+  frame = await with_iframe(scope);
+}, 'global setup');
+
+promise_test(async (t) => {
+  frame.contentWindow.fetch('dummy.txt?respondWith-not-called');
+  const message = await wait_for_message_from_worker();
+  assert_equals(message, 'RESOLVED');
+}, 'FetchEvent.handled should resolve when respondWith() is not called');
+
+promise_test(async (t) => {
+  frame.contentWindow.fetch(
+      'dummy.txt?respondWith-not-called-and-event-canceled').catch((e) => {});
+  const message = await wait_for_message_from_worker();
+  assert_equals(message, 'REJECTED');
+}, 'FetchEvent.handled should reject when respondWith() is not called and the' +
+    ' event is canceled');
+
+promise_test(async (t) => {
+  frame.contentWindow.fetch(
+      'dummy.txt?respondWith-called-and-promise-resolved');
+  const message = await wait_for_message_from_worker();
+  assert_equals(message, 'RESOLVED');
+}, 'FetchEvent.handled should resolve when the promise provided' +
+    ' to respondWith() is resolved');
+
+promise_test(async (t) => {
+  frame.contentWindow.fetch(
+      'dummy.txt?respondWith-called-and-promise-resolved-to-invalid-response')
+      .catch((e) => {});
+  const message = await wait_for_message_from_worker();
+  assert_equals(message, 'REJECTED');
+}, 'FetchEvent.handled should reject when the promise provided' +
+    ' to respondWith() is resolved to an invalid response');
+
+promise_test(async (t) => {
+  frame.contentWindow.fetch(
+      'dummy.txt?respondWith-called-and-promise-rejected').catch((e) => {});
+  const message = await wait_for_message_from_worker();
+  assert_equals(message, 'REJECTED');
+}, 'FetchEvent.handled should reject when the promise provided to' +
+    ' respondWith() is rejected');
+
+// Global cleanup: the final promise_test.
+promise_test(async (t) => {
+  if (frame)
+    frame.remove();
+  await service_worker_unregister(t, scope);
+}, 'global cleanup');
+</script>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js
new file mode 100644
index 0000000..4af58e2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js
@@ -0,0 +1,41 @@
+// This worker reports back the final state of FetchEvent.handled (RESOLVED or
+// REJECTED) to the test.
+
+// Send a message to the client with the client id.
+function send_message_to_client(message, clientId) {
+  clients.get(clientId).then((client) => {
+    client.postMessage(message);
+  });
+}
+
+self.addEventListener('fetch', function(event) {
+  const clientId = event.clientId;
+  try {
+    event.handled.then(() => {
+      send_message_to_client('RESOLVED', clientId);
+    }, () => {
+      send_message_to_client('REJECTED', clientId);
+    });
+  } catch (e) {
+    send_message_to_client('FAILED', clientId);
+    return;
+  }
+
+  const search = new URL(event.request.url).search;
+  switch (search) {
+    case '?respondWith-not-called':
+      break;
+    case '?respondWith-not-called-and-event-canceled':
+      event.preventDefault();
+      break;
+    case '?respondWith-called-and-promise-resolved':
+      event.respondWith(Promise.resolve(new Response('body')));
+      break;
+    case '?respondWith-called-and-promise-resolved-to-invalid-response':
+      event.respondWith(Promise.resolve('invalid response'));
+      break;
+    case '?respondWith-called-and-promise-rejected':
+      event.respondWith(Promise.reject(new Error('respondWith rejected')));
+      break;
+  }
+});
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/untriaged/LICENSE b/third_party/blink/web_tests/external/wpt/shadow-dom/untriaged/LICENSE
deleted file mode 100644
index 531fac43..0000000
--- a/third_party/blink/web_tests/external/wpt/shadow-dom/untriaged/LICENSE
+++ /dev/null
@@ -1,107 +0,0 @@
-Copyright 2012, Google Inc.
-All rights reserved.
-
-Licensed under the W3C Test Suite License (the "License"); you may not
-use this software except in compliance with the License. You may
-obtain a copy of the License at
-
-    http://www.w3.org/Consortium/Legal/2008/04-testsuite-license.html
-
-Alternatively, this software may be distributed under the terms of the
-W3C 3-clause BSD License. You may obtain a copy of the W3C 3-clause
-BSD License at
-
-    http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
-
-
-W3C Test Suite Licence
-
-This document, Test Suites and other documents that link to this
-statement are provided by the copyright holders under the following
-license: By using and/or copying this document, or the W3C document
-from which this statement is linked, you (the licensee) agree that you
-have read, understood, and will comply with the following terms and
-conditions:
-
-Permission to copy, and distribute the contents of this document, or
-the W3C document from which this statement is linked, in any medium
-for any purpose and without fee or royalty is hereby granted, provided
-that you include the following on ALL copies of the document, or
-portions thereof, that you use:
-
-   1. A link or URL to the original W3C document.
-   2. The pre-existing copyright notice of the original author, or if
-it doesn't exist, a notice (hypertext is preferred, but a textual
-representation is permitted) of the form: "Copyright ©
-[$date-of-document] World Wide Web Consortium, (Massachusetts
-Institute of Technology, European Research Consortium for Informatics
-and Mathematics, Keio University) and others. All Rights
-Reserved. http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html"
-   3. If it exists, the STATUS of the W3C document.  When space
-permits, inclusion of the full text of this NOTICE should be
-provided. We request that authorship attribution be provided in any
-software, documents, or other items or products that you create
-pursuant to the implementation of the contents of this document, or
-any portion thereof.
-
-No right to create modifications or derivatives of W3C documents is
-granted pursuant to this license. However, if additional requirements
-(documented in the Copyright FAQ) are satisfied, the right to create
-modifications or derivatives is sometimes granted by the W3C to
-individuals complying with those requirements.
-
-If a Test Suite distinguishes the test harness (or, framework for
-navigation) and the actual tests, permission is given to remove or
-alter the harness or navigation if the Test Suite in question allows
-to do so. The tests themselves shall NOT be changed in any way.
-
-The name and trademarks of W3C and other copyright holders may NOT be
-used in advertising or publicity pertaining to this document or other
-documents that link to this statement without specific, written prior
-permission. Title to copyright in this document will at all times
-remain with copyright holders. Permission is given to use the
-trademarked string W3C within claims of performance concerning W3C
-Specifications or features described therein, and there only, if the
-test suite so authorizes.
-
-THIS WORK IS PROVIDED BY W3C, MIT, ERCIM, KEIO UNIVERSITY, THE
-COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL W3C, MIT, ERCIM, KEIO UNIVERSITY, THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-
-W3C 3-clause BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-   * Redistributions of works must retain the original copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the original
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of the W3C nor the names of its contributors may
-be used to endorse or promote products derived from this work without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/LICENSE b/third_party/blink/web_tests/external/wpt/tools/wptrunner/LICENSE
deleted file mode 100644
index 45896e6..0000000
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-W3C 3-clause BSD License
-
-http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of works must retain the original copyright notice,
-  this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the original copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
-
-* Neither the name of the W3C nor the names of its contributors may be
-  used to endorse or promote products derived from this work without
-  specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/update/sync.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/update/sync.py
index 0d75a12..0a41f706 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/update/sync.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/update/sync.py
@@ -10,37 +10,6 @@
 
 here = os.path.abspath(os.path.split(__file__)[0])
 
-bsd_license = """W3C 3-clause BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of works must retain the original copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the original copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
-
-* Neither the name of the W3C nor the names of its contributors may be
-  used to endorse or promote products derived from this work without
-  specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-"""
-
 
 def copy_wpt_tree(tree, dest, excludes=None, includes=None):
     """Copy the working copy of a Tree to a destination directory.
@@ -84,16 +53,6 @@
         dest_path = os.path.join(dest, destination, os.path.split(source)[1])
         shutil.copy2(source_path, dest_path)
 
-    add_license(dest)
-
-
-def add_license(dest):
-    """Write the bsd license string to a LICENSE file.
-
-    :param dest: Directory in which to place the LICENSE file."""
-    with open(os.path.join(dest, "LICENSE"), "w") as f:
-        f.write(bsd_license)
-
 
 class UpdateCheckout(Step):
     """Pull changes from upstream into the local sync tree."""
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptserve/LICENSE b/third_party/blink/web_tests/external/wpt/tools/wptserve/LICENSE
deleted file mode 100644
index 45896e6..0000000
--- a/third_party/blink/web_tests/external/wpt/tools/wptserve/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-W3C 3-clause BSD License
-
-http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-* Redistributions of works must retain the original copyright notice,
-  this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the original copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
-
-* Neither the name of the W3C nor the names of its contributors may be
-  used to endorse or promote products derived from this work without
-  specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/blink/web_tests/fast/dom/HTMLScriptElement/script-append-child-in-detached-document-expected.txt b/third_party/blink/web_tests/fast/dom/HTMLScriptElement/script-append-child-in-detached-document-expected.txt
new file mode 100644
index 0000000..a6146aa
--- /dev/null
+++ b/third_party/blink/web_tests/fast/dom/HTMLScriptElement/script-append-child-in-detached-document-expected.txt
@@ -0,0 +1 @@
+PASS unless crash
diff --git a/third_party/blink/web_tests/fast/dom/HTMLScriptElement/script-append-child-in-detached-document.html b/third_party/blink/web_tests/fast/dom/HTMLScriptElement/script-append-child-in-detached-document.html
new file mode 100644
index 0000000..697f022
--- /dev/null
+++ b/third_party/blink/web_tests/fast/dom/HTMLScriptElement/script-append-child-in-detached-document.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+<iframe id="i" src="about:blank"></iframe>
+<script>
+if (window.testRunner)
+  testRunner.dumpAsText();
+var i_doc = i.contentDocument;
+i.remove();
+var script = i_doc.createElement("script");
+script.appendChild(i_doc.createTextNode("foo"));
+i_doc.body.appendChild(script);
+</script>
+<p>PASS unless crash</p>
+</body>
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/month-picker/month-picker-this-month-button.html b/third_party/blink/web_tests/virtual/controls-refresh/month-picker/month-picker-this-month-button.html
index f5dbe18c..9f83474 100644
--- a/third_party/blink/web_tests/virtual/controls-refresh/month-picker/month-picker-this-month-button.html
+++ b/third_party/blink/web_tests/virtual/controls-refresh/month-picker/month-picker-this-month-button.html
@@ -8,11 +8,13 @@
 <script src="../../../fast/forms/calendar-picker/resources/calendar-picker-common.js"></script>
 </head>
 <body>
-<input type="month" id="month" value="2019-02">
+<input type="month" id="month0" value="2019-02">
+<input type="month" id="month1" value="2019-02">
+<input type="month" id="month2" value="2019-02" max="2019-05">
 <script>
 
 promise_test(() => {
-  let monthElement = document.getElementById('month');
+  let monthElement = document.getElementById('month0');
   return openPickerWithPromise(monthElement)
   .then(() => {
     clickThisMonthButton();
@@ -23,10 +25,42 @@
     today.setDate(1);
     let expectedTodayDateString = today.toDateString();
 
-     assert_equals(actualTodayDateString, expectedTodayDateString, "'This month button should have updated in-page control to this month");
-     assert_equals(internals.pagePopupWindow, null, "Click on 'This month button should close popup.");
+     assert_equals(actualTodayDateString, expectedTodayDateString, "'This month' button should have updated in-page control to this month");
+     assert_equals(internals.pagePopupWindow, null, "Click on 'This month' button should close popup.");
   });
-}, "Date picker: 'This month' button should select current month");
+}, "Date picker: 'This month' button should select current month when clicked");
+
+promise_test(() => {
+  let monthElement = document.getElementById('month1');
+  return openPickerWithPromise(monthElement)
+  .then(() => {
+    eventSender.keyDown('Tab'); // Tab over to the 'This month' button
+    eventSender.keyDown('Enter');
+
+    let splitDate = monthElement.value.split('-');
+    let actualTodayDateString = new Date(splitDate[0], splitDate[1] - 1).toDateString();
+    let today = new Date();
+    today.setDate(1);
+    let expectedTodayDateString = today.toDateString();
+
+     assert_equals(actualTodayDateString, expectedTodayDateString, "'This month' button should have updated in-page control to this month");
+     assert_equals(internals.pagePopupWindow, null, "Click on 'This month' button should close popup.");
+  });
+}, "Date picker: 'This month' button should select current month when activated with Enter key");
+
+promise_test(() => {
+  let monthElement = document.getElementById('month2');
+  return openPickerWithPromise(monthElement)
+  .then(() => {
+    clickThisMonthButton();
+
+     assert_equals(monthElement.value, "2019-02", "Click on disabled 'This month' button shouldn't change date.");
+     assert_not_equals(internals.pagePopupWindow, null, "Click on disabled 'This month' button shouldn't close popup.");
+
+     eventSender.keyDown('Enter');
+     assert_not_equals(internals.pagePopupWindow, null, "Enter key should close popup.");
+  });
+}, "Date picker: 'This month' button should be disabled when current month is not valid");
 
 </script>
 </body>
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 71deaaf..12fff8b 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -18907,6 +18907,48 @@
   </description>
 </action>
 
+<action name="SharingHubAndroid.CopyURLSelected">
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    The &quot;Copy URL&quot; option was selected in the sharing hub.
+  </description>
+</action>
+
+<action name="SharingHubAndroid.MoreSelected">
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    The &quot;More...&quot; option was selected in the sharing hub.
+  </description>
+</action>
+
+<action name="SharingHubAndroid.QRCodeSelected">
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    The &quot;QR Code&quot; option was selected in the sharing hub.
+  </description>
+</action>
+
+<action name="SharingHubAndroid.ScreenshotSelected">
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    The &quot;Screenshot&quot; option was selected in the sharing hub.
+  </description>
+</action>
+
+<action name="SharingHubAndroid.SendTabToSelfSelected">
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    The &quot;Send to your devices&quot; option was selected in the sharing hub.
+  </description>
+</action>
+
+<action name="SharingHubAndroid.ThirdPartyAppSelected">
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    A third party option was selected in the sharing hub.
+  </description>
+</action>
+
 <action name="Shelf_AlignmentSetBottom">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 19e3aae..c7df1f0 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -14566,6 +14566,7 @@
 <enum name="DesksCreationRemovalSource">
   <int value="0" label="Button pressed"/>
   <int value="1" label="Keyboard shortcut"/>
+  <int value="2" label="Desks restore on first signin"/>
 </enum>
 
 <enum name="DesksMoveWindowFromActiveDeskSource">
@@ -16197,6 +16198,7 @@
   <int value="10" label="OpenFolder"/>
   <int value="11" label="Resume"/>
   <int value="12" label="RetryDownload"/>
+  <int value="13" label="OpenDuringScanning"/>
 </enum>
 
 <enum name="DownloadedFileAction">
@@ -22297,6 +22299,7 @@
   <int value="1442" label="AUTOFILLASSISTANTPRIVATE_PROVIDEUSERDATA"/>
   <int value="1443" label="PASSWORDSPRIVATE_ISOPTEDINFORACCOUNTSTORAGE"/>
   <int value="1444" label="AUTOTESTPRIVATE_PINSHELFICON"/>
+  <int value="1445" label="AUTOTESTPRIVATE_WAITFOROVERVIEWSTATE"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -26548,6 +26551,9 @@
   <int value="3163" label="V8ArrayPrototypeHasElements"/>
   <int value="3164" label="V8ObjectPrototypeHasElements"/>
   <int value="3165" label="DisallowDocumentAccess"/>
+  <int value="3166" label="XRSessionRequestHitTestSource"/>
+  <int value="3167" label="XRSessionRequestHitTestSourceForTransientInput"/>
+  <int value="3168" label="XRDOMOverlay"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 236efcc0..dc38a381 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -102,13 +102,17 @@
     "//components/crash/content/tools/generate_breakpad_symbols.py",
   ]
   data_deps = [
-    "//third_party/breakpad:dump_syms",
     "//third_party/catapult:telemetry_chrome_test_support",
     "//tools/metrics:metrics_python_tests",
   ]
 
   if (!is_win) {
     data_deps += [
+      # This is defined for Windows, but is unused by Telemetry on
+      # Windows, and including it can have issues when cross-compiling
+      # for Arm-based Windows.
+      "//third_party/breakpad:dump_syms",
+
       # These explicitly not defined for Windows builds in Breakpad.
       "//third_party/breakpad:minidump_dump",
       "//third_party/breakpad:minidump_stackwalk",
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css
index b13bef2..c3ead72 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css
+++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css
@@ -171,8 +171,8 @@
 }
 
 :host([files-ng]) cr-button {
-  --hover-bg-color: rgba(255, 255, 255, .04);
-  --ink-color: rgba(255, 255, 255, .88);
+  --hover-bg-color: rgba(255, 255, 255, 4%);
+  --ink-color: rgba(255, 255, 255, 88%);
   --text-color: currentColor;
   border: 2px solid transparent;
   border-radius: 50%;
@@ -258,7 +258,7 @@
 }
 
 :host(:not([files-ng])) cr-button:focus:not(:active) {
-  box-shadow: 0 0 0 1px rgba(66, 133, 244, 0.5);
+  box-shadow: 0 0 0 1px rgba(66, 133, 244, 50%);
   font-weight: bold;
 }
 
@@ -267,7 +267,7 @@
 }
 
 #metadata-box {
-  background-color: rgba(20, 22, 24, 0.8);
+  background-color: rgba(20, 22, 24, 80%);
   bottom: 0;
   height: 100%;
   margin: 0;
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc
index 5e87952..901ac87 100644
--- a/ui/native_theme/common_theme.cc
+++ b/ui/native_theme/common_theme.cc
@@ -88,17 +88,12 @@
         return gfx::kGoogleGrey900;
 
       // MenuItem
-      case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
-      case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
       case NativeTheme::kColorId_HighlightedMenuItemForegroundColor:
       case NativeTheme::kColorId_MenuDropIndicator:
         return gfx::kGoogleGrey200;
       case NativeTheme::kColorId_MenuBorderColor:
       case NativeTheme::kColorId_MenuSeparatorColor:
         return gfx::kGoogleGrey800;
-      case NativeTheme::kColorId_MenuBackgroundColor:
-        return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900,
-                                       0.04f);
       case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor:
         return SkColorSetRGB(0x32, 0x36, 0x39);
       case NativeTheme::kColorId_MenuItemAlertBackgroundColor:
@@ -106,6 +101,15 @@
       case NativeTheme::kColorId_MenuItemMinorTextColor:
         return gfx::kGoogleGrey500;
 
+      // Dropdown
+      case NativeTheme::kColorId_DropdownBackgroundColor:
+        return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900,
+                                       0.04f);
+      case NativeTheme::kColorId_DropdownForegroundColor:
+        return gfx::kGoogleGrey200;
+      case NativeTheme::kColorId_DropdownSelectedForegroundColor:
+        return gfx::kGoogleGrey200;
+
       // Label
       case NativeTheme::kColorId_LabelEnabledColor:
       case NativeTheme::kColorId_LabelTextSelectionColor:
@@ -266,21 +270,23 @@
 
     // MenuItem
     case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
+      return base_theme->GetSystemColor(
+          NativeTheme::kColorId_DropdownForegroundColor, color_scheme);
     case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
+      return base_theme->GetSystemColor(
+          NativeTheme::kColorId_DropdownSelectedForegroundColor, color_scheme);
     case NativeTheme::kColorId_HighlightedMenuItemForegroundColor:
     case NativeTheme::kColorId_MenuDropIndicator:
       return kPrimaryTextColor;
-    case NativeTheme::kColorId_FocusedMenuItemBackgroundColor: {
-      const SkColor bg = base_theme->GetSystemColor(
-          NativeTheme::kColorId_MenuBackgroundColor, color_scheme);
-      return color_utils::BlendForMinContrast(bg, bg, base::nullopt, 1.67f)
-          .color;
-    }
+    case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
+      return base_theme->GetSystemColor(
+          NativeTheme::kColorId_DropdownSelectedBackgroundColor, color_scheme);
     case NativeTheme::kColorId_MenuBorderColor:
     case NativeTheme::kColorId_MenuSeparatorColor:
       return gfx::kGoogleGrey300;
     case NativeTheme::kColorId_MenuBackgroundColor:
-      return SK_ColorWHITE;
+      return base_theme->GetSystemColor(
+          NativeTheme::kColorId_DropdownBackgroundColor, color_scheme);
     case NativeTheme::kColorId_DisabledMenuItemForegroundColor: {
       const SkColor bg = base_theme->GetSystemColor(
           NativeTheme::kColorId_MenuBackgroundColor, color_scheme);
@@ -296,6 +302,20 @@
     case NativeTheme::kColorId_MenuItemAlertBackgroundColor:
       return gfx::kGoogleBlue600;
 
+    // Dropdown
+    case NativeTheme::kColorId_DropdownBackgroundColor:
+      return SK_ColorWHITE;
+    case NativeTheme::kColorId_DropdownForegroundColor:
+      return kPrimaryTextColor;
+    case NativeTheme::kColorId_DropdownSelectedBackgroundColor: {
+      const SkColor bg = base_theme->GetSystemColor(
+          NativeTheme::kColorId_MenuBackgroundColor, color_scheme);
+      return color_utils::BlendForMinContrast(bg, bg, base::nullopt, 1.67f)
+          .color;
+    }
+    case NativeTheme::kColorId_DropdownSelectedForegroundColor:
+      return kPrimaryTextColor;
+
     // Label
     case NativeTheme::kColorId_LabelEnabledColor:
     case NativeTheme::kColorId_LabelTextSelectionColor:
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index 2833b34..832585d 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -363,6 +363,11 @@
     kColorId_HighlightedMenuItemBackgroundColor,
     kColorId_HighlightedMenuItemForegroundColor,
     kColorId_MenuItemAlertBackgroundColor,
+    // Dropdown
+    kColorId_DropdownBackgroundColor,
+    kColorId_DropdownForegroundColor,
+    kColorId_DropdownSelectedBackgroundColor,
+    kColorId_DropdownSelectedForegroundColor,
     // Label
     kColorId_LabelEnabledColor,
     kColorId_LabelDisabledColor,
diff --git a/ui/shell_dialogs/base_shell_dialog_win.cc b/ui/shell_dialogs/base_shell_dialog_win.cc
index d434d86..1ab281d 100644
--- a/ui/shell_dialogs/base_shell_dialog_win.cc
+++ b/ui/shell_dialogs/base_shell_dialog_win.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/win/scoped_com_initializer.h"
 
 namespace ui {
@@ -19,8 +20,8 @@
 // have a situation where a modal dialog in one window blocks the appearance
 // of a modal dialog in another.
 scoped_refptr<base::SingleThreadTaskRunner> CreateDialogTaskRunner() {
-  return CreateCOMSTATaskRunner(
-      {base::ThreadPool(), base::TaskPriority::USER_BLOCKING,
+  return base::ThreadPool::CreateCOMSTATaskRunner(
+      {base::TaskPriority::USER_BLOCKING,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()},
       base::SingleThreadTaskRunnerThreadMode::DEDICATED);
 }
diff --git a/ui/views/animation/ink_drop_highlight.cc b/ui/views/animation/ink_drop_highlight.cc
index a65919c..6bd95dd 100644
--- a/ui/views/animation/ink_drop_highlight.cc
+++ b/ui/views/animation/ink_drop_highlight.cc
@@ -28,9 +28,6 @@
 // The opacity of the highlight when it is not visible.
 constexpr float kHiddenOpacity = 0.0f;
 
-// Default opacity of the highlight.
-constexpr float kDefaultOpacity = 0.128f;
-
 }  // namespace
 
 std::string ToString(InkDropHighlight::AnimationType animation_type) {
@@ -40,24 +37,16 @@
     case InkDropHighlight::AnimationType::kFadeOut:
       return std::string("FADE_OUT");
   }
-  NOTREACHED()
-      << "Should never be reached but is necessary for some compilers.";
-  return std::string("UNKNOWN");
 }
 
 InkDropHighlight::InkDropHighlight(
     const gfx::PointF& center_point,
     std::unique_ptr<BasePaintedLayerDelegate> layer_delegate)
     : center_point_(center_point),
-      // TODO(sammiequon) : Make the default opacity consistent between all
-      // constructors.
-      visible_opacity_(1.f),
-      last_animation_initiated_was_fade_in_(false),
       layer_delegate_(std::move(layer_delegate)),
-      layer_(new ui::Layer()),
-      observer_(nullptr) {
+      layer_(std::make_unique<ui::Layer>()) {
   const gfx::RectF painted_bounds = layer_delegate_->GetPaintedBounds();
-  size_ = explode_size_ = painted_bounds.size();
+  size_ = painted_bounds.size();
 
   layer_->SetBounds(gfx::ToEnclosingRect(painted_bounds));
   layer_->SetFillsBoundsOpaquely(false);
@@ -73,9 +62,9 @@
                                    SkColor color)
     : InkDropHighlight(
           center_point,
-          std::unique_ptr<BasePaintedLayerDelegate>(
-              new RoundedRectangleLayerDelegate(color, size, corner_radius))) {
-  visible_opacity_ = kDefaultOpacity;
+          std::make_unique<RoundedRectangleLayerDelegate>(color,
+                                                          size,
+                                                          corner_radius)) {
   layer_->SetOpacity(visible_opacity_);
 }
 
@@ -86,11 +75,7 @@
     : InkDropHighlight(gfx::SizeF(size), corner_radius, center_point, color) {}
 
 InkDropHighlight::InkDropHighlight(const gfx::SizeF& size, SkColor base_color)
-    : last_animation_initiated_was_fade_in_(false), observer_(nullptr) {
-  size_ = explode_size_ = size;
-  visible_opacity_ = kDefaultOpacity;
-
-  layer_ = std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
+    : size_(size), layer_(std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR)) {
   layer_->SetColor(base_color);
   layer_->SetBounds(gfx::Rect(gfx::ToRoundedSize(size)));
   layer_->SetVisible(false);
@@ -112,12 +97,11 @@
 void InkDropHighlight::FadeIn(const base::TimeDelta& duration) {
   layer_->SetOpacity(kHiddenOpacity);
   layer_->SetVisible(true);
-  AnimateFade(AnimationType::kFadeIn, duration, size_, size_);
+  AnimateFade(AnimationType::kFadeIn, duration);
 }
 
-void InkDropHighlight::FadeOut(const base::TimeDelta& duration, bool explode) {
-  AnimateFade(AnimationType::kFadeOut, duration, size_,
-              explode ? explode_size_ : size_);
+void InkDropHighlight::FadeOut(const base::TimeDelta& duration) {
+  AnimateFade(AnimationType::kFadeOut, duration);
 }
 
 test::InkDropHighlightTestApi* InkDropHighlight::GetTestApi() {
@@ -125,16 +109,14 @@
 }
 
 void InkDropHighlight::AnimateFade(AnimationType animation_type,
-                                   const base::TimeDelta& duration,
-                                   const gfx::SizeF& initial_size,
-                                   const gfx::SizeF& target_size) {
+                                   const base::TimeDelta& duration) {
   const base::TimeDelta effective_duration =
       gfx::Animation::ShouldRenderRichAnimation() ? duration
                                                   : base::TimeDelta();
   last_animation_initiated_was_fade_in_ =
       animation_type == AnimationType::kFadeIn;
 
-  layer_->SetTransform(CalculateTransform(initial_size));
+  layer_->SetTransform(CalculateTransform());
 
   // The |animation_observer| will be destroyed when the
   // AnimationStartedCallback() returns true.
@@ -161,33 +143,16 @@
   opacity_sequence->AddObserver(animation_observer);
   animator->StartAnimation(opacity_sequence);
 
-  if (initial_size != target_size) {
-    std::unique_ptr<ui::LayerAnimationElement> transform_element =
-        ui::LayerAnimationElement::CreateTransformElement(
-            CalculateTransform(target_size), effective_duration);
-
-    ui::LayerAnimationSequence* transform_sequence =
-        new ui::LayerAnimationSequence(std::move(transform_element));
-
-    transform_sequence->AddObserver(animation_observer);
-    animator->StartAnimation(transform_sequence);
-  }
-
   animation_observer->SetActive();
 }
 
-gfx::Transform InkDropHighlight::CalculateTransform(
-    const gfx::SizeF& size) const {
+gfx::Transform InkDropHighlight::CalculateTransform() const {
   gfx::Transform transform;
   // No transform needed for a solid color layer.
   if (!layer_delegate_)
     return transform;
 
   transform.Translate(center_point_.x(), center_point_.y());
-  // TODO(bruthig): Fix the InkDropHighlight to work well when initialized with
-  // a (0x0) size. See https://crbug.com/661618.
-  transform.Scale(size_.width() == 0 ? 0 : size.width() / size_.width(),
-                  size_.height() == 0 ? 0 : size.height() / size_.height());
   gfx::Vector2dF layer_offset = layer_delegate_->GetCenteringOffset();
   transform.Translate(-layer_offset.x(), -layer_offset.y());
 
diff --git a/ui/views/animation/ink_drop_highlight.h b/ui/views/animation/ink_drop_highlight.h
index 6a9e001..110cfdb 100644
--- a/ui/views/animation/ink_drop_highlight.h
+++ b/ui/views/animation/ink_drop_highlight.h
@@ -68,8 +68,6 @@
     observer_ = observer;
   }
 
-  void set_explode_size(const gfx::SizeF& size) { explode_size_ = size; }
-
   void set_visible_opacity(float visible_opacity) {
     visible_opacity_ = visible_opacity;
   }
@@ -81,10 +79,8 @@
   // Fades in the highlight visual over the given |duration|.
   void FadeIn(const base::TimeDelta& duration);
 
-  // Fades out the highlight visual over the given |duration|. If |explode| is
-  // true then the highlight will animate a size increase in addition to the
-  // fade out.
-  void FadeOut(const base::TimeDelta& duration, bool explode);
+  // Fades out the highlight visual over the given |duration|.
+  void FadeOut(const base::TimeDelta& duration);
 
   // The root Layer that can be added in to a Layer tree.
   ui::Layer* layer() { return layer_.get(); }
@@ -97,16 +93,13 @@
  private:
   friend class test::InkDropHighlightTestApi;
 
-  // Animates a fade in/out as specified by |animation_type| combined with a
-  // transformation from the |initial_size| to the |target_size| over the given
+  // Animates a fade in/out as specified by |animation_type| over the given
   // |duration|.
   void AnimateFade(AnimationType animation_type,
-                   const base::TimeDelta& duration,
-                   const gfx::SizeF& initial_size,
-                   const gfx::SizeF& target_size);
+                   const base::TimeDelta& duration);
 
-  // Calculates the Transform to apply to |layer_| for the given |size|.
-  gfx::Transform CalculateTransform(const gfx::SizeF& size) const;
+  // Calculates the Transform to apply to |layer_|.
+  gfx::Transform CalculateTransform() const;
 
   // The callback that will be invoked when a fade in/out animation is started.
   void AnimationStartedCallback(
@@ -121,20 +114,16 @@
   // The size of the highlight shape when fully faded in.
   gfx::SizeF size_;
 
-  // The target size of the highlight shape when it expands during a fade out
-  // animation.
-  gfx::SizeF explode_size_;
-
   // The center point of the highlight shape in the parent Layer's coordinate
   // space.
   gfx::PointF center_point_;
 
   // The opacity for the fully visible state of the highlight.
-  float visible_opacity_;
+  float visible_opacity_ = 0.128f;
 
   // True if the last animation to be initiated was a kFadeIn, and false
   // otherwise.
-  bool last_animation_initiated_was_fade_in_;
+  bool last_animation_initiated_was_fade_in_ = false;
 
   // The LayerDelegate that paints the highlight |layer_|. Null if |layer_| is a
   // solid color layer.
@@ -143,7 +132,7 @@
   // The visual highlight layer.
   std::unique_ptr<ui::Layer> layer_;
 
-  InkDropHighlightObserver* observer_;
+  InkDropHighlightObserver* observer_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(InkDropHighlight);
 };
diff --git a/ui/views/animation/ink_drop_highlight_unittest.cc b/ui/views/animation/ink_drop_highlight_unittest.cc
index f7368dc6..dfb7b25 100644
--- a/ui/views/animation/ink_drop_highlight_unittest.cc
+++ b/ui/views/animation/ink_drop_highlight_unittest.cc
@@ -94,8 +94,7 @@
   test_api()->CompleteAnimations();
   EXPECT_TRUE(ink_drop_highlight()->IsFadingInOrVisible());
 
-  ink_drop_highlight()->FadeOut(base::TimeDelta::FromSeconds(1),
-                                false /* explode */);
+  ink_drop_highlight()->FadeOut(base::TimeDelta::FromSeconds(1));
   EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible());
 
   test_api()->CompleteAnimations();
@@ -132,8 +131,7 @@
   EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn,
             observer()->last_animation_started_context());
 
-  ink_drop_highlight()->FadeOut(base::TimeDelta::FromSeconds(1),
-                                false /* explode */);
+  ink_drop_highlight()->FadeOut(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(InkDropHighlight::AnimationType::kFadeOut,
             observer()->last_animation_started_context());
 
@@ -158,8 +156,7 @@
     return;
 
   ink_drop_highlight()->FadeIn(base::TimeDelta::FromSeconds(1));
-  ink_drop_highlight()->FadeOut(base::TimeDelta::FromSeconds(1),
-                                false /* explode */);
+  ink_drop_highlight()->FadeOut(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(2, observer()->last_animation_ended_ordinal());
   EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn,
@@ -175,8 +172,7 @@
   ink_drop_highlight()->FadeIn(base::TimeDelta::FromSeconds(1));
   test_api()->CompleteAnimations();
 
-  ink_drop_highlight()->FadeOut(base::TimeDelta::FromMilliseconds(0),
-                                false /* explode */);
+  ink_drop_highlight()->FadeOut(base::TimeDelta::FromMilliseconds(0));
   test_api()->CompleteAnimations();
   EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible());
 }
@@ -203,15 +199,14 @@
 TEST_F(InkDropHighlightTest, AnimatingAZeroSizeHighlight) {
   InitHighlight(std::make_unique<InkDropHighlight>(
       gfx::Size(0, 0), 3, gfx::PointF(), SK_ColorBLACK));
-  ink_drop_highlight()->FadeOut(base::TimeDelta::FromMilliseconds(0),
-                                false /* explode */);
+  ink_drop_highlight()->FadeOut(base::TimeDelta::FromMilliseconds(0));
 }
 
 TEST_F(InkDropHighlightTest, TransformIsPixelAligned) {
-  const float kEpsilon = 0.001f;
-  gfx::Size highlight_size(10, 10);
+  constexpr float kEpsilon = 0.001f;
+  constexpr gfx::Size kHighlightSize(10, 10);
   InitHighlight(std::make_unique<InkDropHighlight>(
-      highlight_size, 3, gfx::PointF(3.5f, 3.5f), SK_ColorYELLOW));
+      kHighlightSize, 3, gfx::PointF(3.5f, 3.5f), SK_ColorYELLOW));
   const gfx::PointF layer_origin(
       ink_drop_highlight()->layer()->bounds().origin());
   for (auto dsf : {1.25, 1.33, 1.5, 1.6, 1.75, 1.8, 2.25}) {
@@ -220,8 +215,7 @@
                  << "Device Scale Factor: " << dsf << std::endl);
     ink_drop_highlight()->layer()->OnDeviceScaleFactorChanged(dsf);
 
-    const gfx::SizeF size(highlight_size);
-    gfx::Transform transform = test_api()->CalculateTransform(size);
+    gfx::Transform transform = test_api()->CalculateTransform();
     gfx::Point3F transformed_layer_origin(layer_origin.x(), layer_origin.y(),
                                           0);
     transform.TransformPoint(&transformed_layer_origin);
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 47209d8a..5ab7e83 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -161,21 +161,6 @@
   return ripple;
 }
 
-std::unique_ptr<InkDropHighlight>
-InkDropHostView::CreateDefaultInkDropHighlight(const gfx::PointF& center_point,
-                                               const gfx::Size& size) const {
-  return CreateSquareInkDropHighlight(center_point, size);
-}
-
-std::unique_ptr<InkDropHighlight> InkDropHostView::CreateSquareInkDropHighlight(
-    const gfx::PointF& center_point,
-    const gfx::Size& size) const {
-  auto highlight = std::make_unique<InkDropHighlight>(
-      size, ink_drop_small_corner_radius_, center_point, GetInkDropBaseColor());
-  highlight->set_explode_size(gfx::SizeF(CalculateLargeInkDropSize(size)));
-  return highlight;
-}
-
 bool InkDropHostView::HasInkDrop() const {
   return !!ink_drop_;
 }
diff --git a/ui/views/animation/ink_drop_host_view.h b/ui/views/animation/ink_drop_host_view.h
index 3a76742..b711c5f0 100644
--- a/ui/views/animation/ink_drop_host_view.h
+++ b/ui/views/animation/ink_drop_host_view.h
@@ -13,10 +13,6 @@
 #include "ui/views/animation/ink_drop_event_handler.h"
 #include "ui/views/view.h"
 
-namespace gfx {
-class PointF;
-}  // namespace gfx
-
 namespace ui {
 class Layer;
 class LocatedEvent;
@@ -168,17 +164,6 @@
       const gfx::Point& center_point,
       const gfx::Size& size) const;
 
-  // TODO(pbos): Migrate uses to CreateSquareInkDropHighlight which this calls
-  // directly.
-  std::unique_ptr<InkDropHighlight> CreateDefaultInkDropHighlight(
-      const gfx::PointF& center_point,
-      const gfx::Size& size = kDefaultInkDropSize) const;
-
-  // Creates a InkDropHighlight centered on |center_point|.
-  std::unique_ptr<InkDropHighlight> CreateSquareInkDropHighlight(
-      const gfx::PointF& center_point,
-      const gfx::Size& size) const;
-
   // Returns true if an ink drop instance has been created.
   bool HasInkDrop() const;
 
diff --git a/ui/views/animation/ink_drop_impl.cc b/ui/views/animation/ink_drop_impl.cc
index 42704ad..22d66c0d 100644
--- a/ui/views/animation/ink_drop_impl.cc
+++ b/ui/views/animation/ink_drop_impl.cc
@@ -101,8 +101,7 @@
     : public InkDropImpl::HighlightState {
  public:
   NoAutoHighlightHiddenState(HighlightStateFactory* state_factory,
-                             base::TimeDelta animation_duration,
-                             bool explode);
+                             base::TimeDelta animation_duration);
 
   // InkDropImpl::HighlightState:
   void Enter() override;
@@ -122,9 +121,6 @@
   // The fade out animation duration.
   base::TimeDelta animation_duration_;
 
-  // True when the highlight should explode while fading out.
-  bool explode_;
-
   DISALLOW_COPY_AND_ASSIGN(NoAutoHighlightHiddenState);
 };
 
@@ -134,8 +130,7 @@
     : public InkDropImpl::HighlightState {
  public:
   NoAutoHighlightVisibleState(HighlightStateFactory* state_factory,
-                              base::TimeDelta animation_duration,
-                              bool explode);
+                              base::TimeDelta animation_duration);
 
   // InkDropImpl::HighlightState:
   void Enter() override;
@@ -156,9 +151,6 @@
   // The fade in animation duration.
   base::TimeDelta animation_duration_;
 
-  // True when the highlight should explode while fading in.
-  bool explode_;
-
   DISALLOW_COPY_AND_ASSIGN(NoAutoHighlightVisibleState);
 };
 
@@ -166,14 +158,12 @@
 
 InkDropImpl::NoAutoHighlightHiddenState::NoAutoHighlightHiddenState(
     HighlightStateFactory* state_factory,
-    base::TimeDelta animation_duration,
-    bool explode)
+    base::TimeDelta animation_duration)
     : InkDropImpl::HighlightState(state_factory),
-      animation_duration_(animation_duration),
-      explode_(explode) {}
+      animation_duration_(animation_duration) {}
 
 void InkDropImpl::NoAutoHighlightHiddenState::Enter() {
-  GetInkDrop()->SetHighlight(false, animation_duration_, explode_);
+  GetInkDrop()->SetHighlight(false, animation_duration_);
 }
 
 void InkDropImpl::NoAutoHighlightHiddenState::ShowOnHoverChanged() {
@@ -200,7 +190,7 @@
     base::TimeDelta animation_duration) {
   if (GetInkDrop()->ShouldHighlight()) {
     GetInkDrop()->SetHighlightState(
-        state_factory()->CreateVisibleState(animation_duration, false));
+        state_factory()->CreateVisibleState(animation_duration));
   }
 }
 
@@ -215,14 +205,12 @@
 
 InkDropImpl::NoAutoHighlightVisibleState::NoAutoHighlightVisibleState(
     HighlightStateFactory* state_factory,
-    base::TimeDelta animation_duration,
-    bool explode)
+    base::TimeDelta animation_duration)
     : InkDropImpl::HighlightState(state_factory),
-      animation_duration_(animation_duration),
-      explode_(explode) {}
+      animation_duration_(animation_duration) {}
 
 void InkDropImpl::NoAutoHighlightVisibleState::Enter() {
-  GetInkDrop()->SetHighlight(true, animation_duration_, explode_);
+  GetInkDrop()->SetHighlight(true, animation_duration_);
 }
 
 void InkDropImpl::NoAutoHighlightVisibleState::ShowOnHoverChanged() {
@@ -249,7 +237,7 @@
     base::TimeDelta animation_duration) {
   if (!GetInkDrop()->ShouldHighlight()) {
     GetInkDrop()->SetHighlightState(
-        state_factory()->CreateHiddenState(animation_duration, false));
+        state_factory()->CreateHiddenState(animation_duration));
   }
 }
 
@@ -270,8 +258,7 @@
     : public InkDropImpl::NoAutoHighlightHiddenState {
  public:
   HideHighlightOnRippleHiddenState(HighlightStateFactory* state_factory,
-                                   base::TimeDelta animation_duration,
-                                   bool explode);
+                                   base::TimeDelta animation_duration);
 
   // InkDropImpl::NoAutoHighlightHiddenState:
   void ShowOnHoverChanged() override;
@@ -304,8 +291,7 @@
     : public InkDropImpl::NoAutoHighlightVisibleState {
  public:
   HideHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
-                                    base::TimeDelta animation_duration,
-                                    bool explode);
+                                    base::TimeDelta animation_duration);
 
   // InkDropImpl::NoAutoHighlightVisibleState:
   void AnimationStarted(InkDropState ink_drop_state) override;
@@ -318,11 +304,9 @@
 
 InkDropImpl::HideHighlightOnRippleHiddenState::HideHighlightOnRippleHiddenState(
     HighlightStateFactory* state_factory,
-    base::TimeDelta animation_duration,
-    bool explode)
+    base::TimeDelta animation_duration)
     : InkDropImpl::NoAutoHighlightHiddenState(state_factory,
-                                              animation_duration,
-                                              explode),
+                                              animation_duration),
       highlight_after_ripple_timer_(nullptr) {}
 
 void InkDropImpl::HideHighlightOnRippleHiddenState::ShowOnHoverChanged() {
@@ -364,7 +348,7 @@
     // |this| may be destroyed after SnapToHidden(), so be sure not to access
     // |any members.
     ink_drop->SetHighlightState(
-        highlight_state_factory->CreateVisibleState(base::TimeDelta(), false));
+        highlight_state_factory->CreateVisibleState(base::TimeDelta()));
   }
 }
 
@@ -376,7 +360,7 @@
     // straight into the animation.
     if (GetInkDrop()->ShouldHighlightBasedOnFocus()) {
       GetInkDrop()->SetHighlightState(
-          state_factory()->CreateVisibleState(base::TimeDelta(), false));
+          state_factory()->CreateVisibleState(base::TimeDelta()));
       return;
     } else {
       StartHighlightAfterRippleTimer();
@@ -400,7 +384,7 @@
   if (GetInkDrop()->GetTargetInkDropState() == InkDropState::HIDDEN &&
       GetInkDrop()->ShouldHighlight()) {
     GetInkDrop()->SetHighlightState(state_factory()->CreateVisibleState(
-        kHighlightFadeInOnRippleHidingDuration, true));
+        kHighlightFadeInOnRippleHidingDuration));
   }
 }
 
@@ -408,17 +392,15 @@
 
 InkDropImpl::HideHighlightOnRippleVisibleState::
     HideHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
-                                      base::TimeDelta animation_duration,
-                                      bool explode)
+                                      base::TimeDelta animation_duration)
     : InkDropImpl::NoAutoHighlightVisibleState(state_factory,
-                                               animation_duration,
-                                               explode) {}
+                                               animation_duration) {}
 
 void InkDropImpl::HideHighlightOnRippleVisibleState::AnimationStarted(
     InkDropState ink_drop_state) {
   if (ink_drop_state != InkDropState::HIDDEN) {
     GetInkDrop()->SetHighlightState(state_factory()->CreateHiddenState(
-        kHighlightFadeOutOnRippleShowingDuration, true));
+        kHighlightFadeOutOnRippleShowingDuration));
   }
 }
 
@@ -432,8 +414,7 @@
     : public InkDropImpl::NoAutoHighlightHiddenState {
  public:
   ShowHighlightOnRippleHiddenState(HighlightStateFactory* state_factory,
-                                   base::TimeDelta animation_duration,
-                                   bool explode);
+                                   base::TimeDelta animation_duration);
 
   // InkDropImpl::NoAutoHighlightHiddenState:
   void AnimationStarted(InkDropState ink_drop_state) override;
@@ -448,8 +429,7 @@
     : public InkDropImpl::NoAutoHighlightVisibleState {
  public:
   ShowHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
-                                    base::TimeDelta animation_duration,
-                                    bool explode);
+                                    base::TimeDelta animation_duration);
 
   // InkDropImpl::NoAutoHighlightVisibleState:
   void ShowOnHoverChanged() override;
@@ -466,17 +446,15 @@
 
 InkDropImpl::ShowHighlightOnRippleHiddenState::ShowHighlightOnRippleHiddenState(
     HighlightStateFactory* state_factory,
-    base::TimeDelta animation_duration,
-    bool explode)
+    base::TimeDelta animation_duration)
     : InkDropImpl::NoAutoHighlightHiddenState(state_factory,
-                                              animation_duration,
-                                              explode) {}
+                                              animation_duration) {}
 
 void InkDropImpl::ShowHighlightOnRippleHiddenState::AnimationStarted(
     InkDropState ink_drop_state) {
   if (ink_drop_state != views::InkDropState::HIDDEN) {
     GetInkDrop()->SetHighlightState(state_factory()->CreateVisibleState(
-        kHighlightFadeInOnRippleShowingDuration, false));
+        kHighlightFadeInOnRippleShowingDuration));
   }
 }
 
@@ -484,11 +462,9 @@
 
 InkDropImpl::ShowHighlightOnRippleVisibleState::
     ShowHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
-                                      base::TimeDelta animation_duration,
-                                      bool explode)
+                                      base::TimeDelta animation_duration)
     : InkDropImpl::NoAutoHighlightVisibleState(state_factory,
-                                               animation_duration,
-                                               explode) {}
+                                               animation_duration) {}
 
 void InkDropImpl::ShowHighlightOnRippleVisibleState::ShowOnHoverChanged() {
   if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
@@ -519,7 +495,7 @@
   if (ink_drop_state == InkDropState::HIDDEN &&
       !GetInkDrop()->ShouldHighlight()) {
     GetInkDrop()->SetHighlightState(state_factory()->CreateHiddenState(
-        kHighlightFadeOutOnRippleHidingDuration, false));
+        kHighlightFadeOutOnRippleHidingDuration));
   }
 }
 
@@ -532,14 +508,14 @@
 InkDropImpl::HighlightStateFactory::CreateStartState() {
   switch (highlight_mode_) {
     case InkDropImpl::AutoHighlightMode::NONE:
-      return std::make_unique<NoAutoHighlightHiddenState>(
-          this, base::TimeDelta(), false);
+      return std::make_unique<NoAutoHighlightHiddenState>(this,
+                                                          base::TimeDelta());
     case InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE:
       return std::make_unique<HideHighlightOnRippleHiddenState>(
-          this, base::TimeDelta(), false);
+          this, base::TimeDelta());
     case InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE:
       return std::make_unique<ShowHighlightOnRippleHiddenState>(
-          this, base::TimeDelta(), false);
+          this, base::TimeDelta());
   }
   // Required for some compilers.
   NOTREACHED();
@@ -548,18 +524,17 @@
 
 std::unique_ptr<InkDropImpl::HighlightState>
 InkDropImpl::HighlightStateFactory::CreateHiddenState(
-    base::TimeDelta animation_duration,
-    bool explode) {
+    base::TimeDelta animation_duration) {
   switch (highlight_mode_) {
     case InkDropImpl::AutoHighlightMode::NONE:
-      return std::make_unique<NoAutoHighlightHiddenState>(
-          this, animation_duration, explode);
+      return std::make_unique<NoAutoHighlightHiddenState>(this,
+                                                          animation_duration);
     case InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE:
       return std::make_unique<HideHighlightOnRippleHiddenState>(
-          this, animation_duration, explode);
+          this, animation_duration);
     case InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE:
       return std::make_unique<ShowHighlightOnRippleHiddenState>(
-          this, animation_duration, explode);
+          this, animation_duration);
   }
   // Required for some compilers.
   NOTREACHED();
@@ -568,18 +543,17 @@
 
 std::unique_ptr<InkDropImpl::HighlightState>
 InkDropImpl::HighlightStateFactory::CreateVisibleState(
-    base::TimeDelta animation_duration,
-    bool explode) {
+    base::TimeDelta animation_duration) {
   switch (highlight_mode_) {
     case InkDropImpl::AutoHighlightMode::NONE:
-      return std::make_unique<NoAutoHighlightVisibleState>(
-          this, animation_duration, explode);
+      return std::make_unique<NoAutoHighlightVisibleState>(this,
+                                                           animation_duration);
     case InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE:
       return std::make_unique<HideHighlightOnRippleVisibleState>(
-          this, animation_duration, explode);
+          this, animation_duration);
     case InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE:
       return std::make_unique<ShowHighlightOnRippleVisibleState>(
-          this, animation_duration, explode);
+          this, animation_duration);
   }
   // Required for some compilers.
   NOTREACHED();
@@ -830,8 +804,7 @@
 }
 
 void InkDropImpl::SetHighlight(bool should_highlight,
-                               base::TimeDelta animation_duration,
-                               bool explode) {
+                               base::TimeDelta animation_duration) {
   if (IsHighlightFadingInOrVisible() == should_highlight)
     return;
 
@@ -839,7 +812,7 @@
     CreateInkDropHighlight();
     highlight_->FadeIn(animation_duration);
   } else {
-    highlight_->FadeOut(animation_duration, explode);
+    highlight_->FadeOut(animation_duration);
   }
 }
 
diff --git a/ui/views/animation/ink_drop_impl.h b/ui/views/animation/ink_drop_impl.h
index 22173d61..46b1b305 100644
--- a/ui/views/animation/ink_drop_impl.h
+++ b/ui/views/animation/ink_drop_impl.h
@@ -171,12 +171,10 @@
     std::unique_ptr<HighlightState> CreateStartState();
 
     std::unique_ptr<HighlightState> CreateHiddenState(
-        base::TimeDelta animation_duration,
-        bool explode);
+        base::TimeDelta animation_duration);
 
     std::unique_ptr<HighlightState> CreateVisibleState(
-        base::TimeDelta animation_duration,
-        bool explode);
+        base::TimeDelta animation_duration);
 
     InkDropImpl* ink_drop() { return ink_drop_; }
 
@@ -244,11 +242,8 @@
 
   // Enables or disables the highlight state based on |should_highlight| and if
   // an animation is triggered it will be scheduled to have the given
-  // |animation_duration|. If |explode| is true the highlight will expand as it
-  // fades out. |explode| is ignored when |should_higlight| is true.
-  void SetHighlight(bool should_highlight,
-                    base::TimeDelta animation_duration,
-                    bool explode);
+  // |animation_duration|.
+  void SetHighlight(bool should_highlight, base::TimeDelta animation_duration);
 
   // Returns true if |this| the highlight should be visible based on the
   // hover/focus status.
diff --git a/ui/views/animation/test/ink_drop_highlight_test_api.cc b/ui/views/animation/test/ink_drop_highlight_test_api.cc
index 83594bf5..f5044535 100644
--- a/ui/views/animation/test/ink_drop_highlight_test_api.cc
+++ b/ui/views/animation/test/ink_drop_highlight_test_api.cc
@@ -26,9 +26,8 @@
   return animators;
 }
 
-gfx::Transform InkDropHighlightTestApi::CalculateTransform(
-    const gfx::SizeF& size) {
-  return ink_drop_highlight()->CalculateTransform(size);
+gfx::Transform InkDropHighlightTestApi::CalculateTransform() {
+  return ink_drop_highlight()->CalculateTransform();
 }
 
 }  // namespace test
diff --git a/ui/views/animation/test/ink_drop_highlight_test_api.h b/ui/views/animation/test/ink_drop_highlight_test_api.h
index c7bec20..75dfa4f2 100644
--- a/ui/views/animation/test/ink_drop_highlight_test_api.h
+++ b/ui/views/animation/test/ink_drop_highlight_test_api.h
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "ui/compositor/test/multi_layer_animator_test_controller.h"
 #include "ui/compositor/test/multi_layer_animator_test_controller_delegate.h"
-#include "ui/gfx/geometry/size_f.h"
 #include "ui/gfx/transform.h"
 
 namespace ui {
@@ -35,7 +34,7 @@
   // MultiLayerAnimatorTestControllerDelegate:
   std::vector<ui::LayerAnimator*> GetLayerAnimators() override;
 
-  gfx::Transform CalculateTransform(const gfx::SizeF& size);
+  gfx::Transform CalculateTransform();
 
  protected:
   InkDropHighlight* ink_drop_highlight() {
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc
index ca9efb3..f41536fd 100644
--- a/ui/views/controls/button/md_text_button.cc
+++ b/ui/views/controls/button/md_text_button.cc
@@ -142,11 +142,13 @@
   // the mask bounds.
   shadows.emplace_back(gfx::Vector2d(0, kYOffset), 2 * kSkiaBlurRadius,
                        theme->GetSystemColor(shadow_color_id));
-  return std::make_unique<InkDropHighlight>(
+  auto highlight = std::make_unique<InkDropHighlight>(
       gfx::RectF(GetLocalBounds()).CenterPoint(),
-      base::WrapUnique(new BorderShadowLayerDelegate(
+      std::make_unique<BorderShadowLayerDelegate>(
           shadows, GetLocalBounds(), theme->GetSystemColor(fill_color_id),
-          corner_radius_)));
+          corner_radius_));
+  highlight->set_visible_opacity(1.0f);
+  return highlight;
 }
 
 void MdTextButton::SetEnabledTextColors(base::Optional<SkColor> color) {
diff --git a/ui/views/view_targeter_delegate.cc b/ui/views/view_targeter_delegate.cc
index b47409d..82f1424 100644
--- a/ui/views/view_targeter_delegate.cc
+++ b/ui/views/view_targeter_delegate.cc
@@ -46,7 +46,7 @@
   View::Views children = root->GetChildrenInZOrder();
   DCHECK_EQ(root->children().size(), children.size());
   for (auto* child : base::Reversed(children)) {
-    if (!child->CanProcessEventsWithinSubtree())
+    if (!child->CanProcessEventsWithinSubtree() || !child->GetEnabled())
       continue;
 
     // Ignore any children which are invisible or do not intersect |rect|.
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index bdcdbb5..0972e7f 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -5403,6 +5403,27 @@
   EXPECT_FALSE(test_view.GetVisible());
 }
 
+TEST_F(ViewTest, TooltipShowsForDisabledView) {
+  auto widget = std::make_unique<Widget>();
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  widget->Init(std::move(params));
+  widget->SetBounds(gfx::Rect(0, 0, 100, 100));
+
+  View enabled_parent;
+  View* const disabled_child =
+      enabled_parent.AddChildView(std::make_unique<View>());
+  disabled_child->SetEnabled(false);
+
+  enabled_parent.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
+  disabled_child->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
+  widget->GetContentsView()->AddChildView(&enabled_parent);
+  widget->Show();
+
+  EXPECT_EQ(disabled_child,
+            enabled_parent.GetTooltipHandlerForPoint(gfx::Point(50, 50)));
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Observer tests.
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm
index 10f9cea..e6767db 100644
--- a/ui/views/widget/native_widget_mac_unittest.mm
+++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -1108,7 +1108,6 @@
   explicit ModalDialogDelegate(ui::ModalType modal_type)
       : modal_type_(modal_type) {}
 
-  void set_can_close(bool value) { can_close_ = value; }
   void SetButtons(int buttons) {
     DialogDelegate::set_buttons(buttons);
     DialogModelChanged();
@@ -1116,11 +1115,9 @@
 
   // DialogDelegateView:
   ui::ModalType GetModalType() const override { return modal_type_; }
-  bool Close() override { return can_close_; }
 
  private:
   const ui::ModalType modal_type_;
-  bool can_close_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
 };
@@ -2361,19 +2358,6 @@
       ]]));
 }
 
-// Test -[NSWindowDelegate windowShouldClose:].
-TEST_F(NativeWidgetMacTest, CanClose) {
-  ModalDialogDelegate* delegate = new ModalDialogDelegate(ui::MODAL_TYPE_NONE);
-  Widget* widget =
-      views::DialogDelegate::CreateDialogWidget(delegate, nullptr, nullptr);
-  NSWindow* window = widget->GetNativeWindow().GetNativeNSWindow();
-  delegate->set_can_close(false);
-  EXPECT_FALSE([[window delegate] windowShouldClose:window]);
-  delegate->set_can_close(true);
-  EXPECT_TRUE([[window delegate] windowShouldClose:window]);
-  widget->CloseNow();
-}
-
 namespace {
 
 // Returns an array of NSTouchBarItemIdentifier (i.e. NSString), extracted from
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index 1303f1b..3c74784 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -141,6 +141,7 @@
       return;
 
     View* target = static_cast<View*>(event->target());
+
     gfx::Point location = event->location();
     if (touch_dnd_enabled_ && event->type() == ui::ET_GESTURE_LONG_PRESS &&
         (!target->drag_controller() ||
@@ -379,18 +380,14 @@
   }
   DCHECK(!explicit_mouse_handler_);
 
-  bool hit_disabled_view = false;
-  // Walk up the tree until we find a view that wants the mouse event.
+  // Walk up the tree from the target until we find a view that wants
+  // the mouse event.
   for (mouse_pressed_handler_ = GetEventHandlerForPoint(event.location());
        mouse_pressed_handler_ && (mouse_pressed_handler_ != this);
        mouse_pressed_handler_ = mouse_pressed_handler_->parent()) {
     DVLOG(1) << "OnMousePressed testing "
              << mouse_pressed_handler_->GetClassName();
-    if (!mouse_pressed_handler_->GetEnabled()) {
-      // Disabled views should eat events instead of propagating them upwards.
-      hit_disabled_view = true;
-      break;
-    }
+    DCHECK(mouse_pressed_handler_->GetEnabled());
 
     // See if this view wants to handle the mouse press.
     ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this),
@@ -430,16 +427,13 @@
 
   // Reset mouse_pressed_handler_ to indicate that no processing is occurring.
   mouse_pressed_handler_ = nullptr;
+  last_click_handler_ = nullptr;
 
   // In the event that a double-click is not handled after traversing the
   // entire hierarchy (even as a single-click when sent to a different view),
   // it must be marked as handled to avoid anything happening from default
   // processing if it the first click-part was handled by us.
-  if (last_click_handler_ && (event.flags() & ui::EF_IS_DOUBLE_CLICK))
-    hit_disabled_view = true;
-
-  last_click_handler_ = nullptr;
-  return hit_disabled_view;
+  return event.flags() & ui::EF_IS_DOUBLE_CLICK;
 }
 
 bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
@@ -500,12 +494,14 @@
 
 void RootView::OnMouseMoved(const ui::MouseEvent& event) {
   View* v = GetEventHandlerForPoint(event.location());
-  // Find the first enabled view, or the existing move handler, whichever comes
-  // first.  The check for the existing handler is because if a view becomes
-  // disabled while handling moves, it's wrong to suddenly send ET_MOUSE_EXITED
-  // and ET_MOUSE_ENTERED events, because the mouse hasn't actually exited yet.
-  while (v && !v->GetEnabled() && (v != mouse_move_handler_))
-    v = v->parent();
+  // Check for a disabled move handler. If the move handler became
+  // disabled while handling moves, it's wrong to suddenly send
+  // ET_MOUSE_EXITED and ET_MOUSE_ENTERED events, because the mouse
+  // hasn't actually exited yet.
+  if (mouse_move_handler_ && !mouse_move_handler_->GetEnabled() &&
+      v->Contains(mouse_move_handler_))
+    v = mouse_move_handler_;
+
   if (v && v != this) {
     if (v != mouse_move_handler_) {
       if (mouse_move_handler_ != nullptr &&
@@ -763,12 +759,6 @@
     //                   |gesture_handler_| to detect if the view has been
     //                   removed from the tree.
     gesture_handler_ = view;
-
-    // Disabled views are permitted to be targets of gesture events, but
-    // gesture events should never actually be dispatched to them. Prevent
-    // dispatch by marking the event as handled.
-    if (!view->GetEnabled())
-      event->SetHandled();
   }
 
   old_dispatch_target_ = event_dispatch_target_;
diff --git a/ui/views/widget/root_view_unittest.cc b/ui/views/widget/root_view_unittest.cc
index a22a46e..5dc1f106 100644
--- a/ui/views/widget/root_view_unittest.cc
+++ b/ui/views/widget/root_view_unittest.cc
@@ -12,6 +12,7 @@
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/views/context_menu_controller.h"
+#include "ui/views/test/test_views.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/view_targeter.h"
 #include "ui/views/widget/root_view.h"
@@ -803,5 +804,60 @@
 
 #endif  // !defined(OS_MACOSX)
 
+TEST_F(RootViewTest, MouseEventDispatchedToClosestEnabledView) {
+  Widget widget;
+  Widget::InitParams init_params =
+      CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+  init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  init_params.bounds = {100, 100, 100, 100};
+  widget.Init(std::move(init_params));
+  widget.Show();
+  internal::RootView* root_view =
+      static_cast<internal::RootView*>(widget.GetRootView());
+  root_view->SetContentsView(new View());
+
+  View* const contents_view = root_view->GetContentsView();
+  EventCountView* const v1 =
+      contents_view->AddChildView(std::make_unique<EventCountView>());
+  EventCountView* const v2 =
+      v1->AddChildView(std::make_unique<EventCountView>());
+  EventCountView* const v3 =
+      v2->AddChildView(std::make_unique<EventCountView>());
+
+  contents_view->SetBoundsRect(gfx::Rect(0, 0, 10, 10));
+  v1->SetBoundsRect(gfx::Rect(0, 0, 10, 10));
+  v2->SetBoundsRect(gfx::Rect(0, 0, 10, 10));
+  v3->SetBoundsRect(gfx::Rect(0, 0, 10, 10));
+
+  v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
+  v2->set_handle_mode(EventCountView::CONSUME_EVENTS);
+  v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
+
+  ui::MouseEvent pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5),
+                               gfx::Point(5, 5), ui::EventTimeForNow(), 0, 0);
+  ui::MouseEvent released_event(ui::ET_MOUSE_RELEASED, gfx::Point(5, 5),
+                                gfx::Point(5, 5), ui::EventTimeForNow(), 0, 0);
+  root_view->OnMousePressed(pressed_event);
+  root_view->OnMouseReleased(released_event);
+  EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(1, v3->GetEventCount(ui::ET_MOUSE_PRESSED));
+
+  v3->SetEnabled(false);
+  root_view->OnMousePressed(pressed_event);
+  root_view->OnMouseReleased(released_event);
+  EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(1, v3->GetEventCount(ui::ET_MOUSE_PRESSED));
+
+  v3->SetEnabled(true);
+  v2->SetEnabled(false);
+  root_view->OnMousePressed(pressed_event);
+  root_view->OnMouseReleased(released_event);
+  EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_PRESSED));
+  EXPECT_EQ(1, v3->GetEventCount(ui::ET_MOUSE_PRESSED));
+}
+
 }  // namespace test
 }  // namespace views
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index 74b82a5..ac5f80e 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -2992,125 +2992,6 @@
   widget->Close();
 }
 
-// Verifies that disabled views are permitted to be set as the default gesture
-// handler in RootView. Also verifies that gesture events targeted to a disabled
-// view are not actually dispatched to the view, but are still marked as
-// handled.
-TEST_F(WidgetTest, DisabledGestureEventTarget) {
-  Widget* widget = CreateTopLevelNativeWidget();
-  widget->SetBounds(gfx::Rect(0, 0, 300, 300));
-
-  // Define a hierarchy of four views (coordinates are in
-  // their parent coordinate space).
-  // v1 (0, 0, 300, 300)
-  //   v2 (0, 0, 100, 100)
-  //     v3 (0, 0, 50, 50)
-  //       v4(0, 0, 10, 10)
-  EventCountView* v1 = new EventCountView();
-  v1->SetBounds(0, 0, 300, 300);
-  EventCountView* v2 = new EventCountView();
-  v2->SetBounds(0, 0, 100, 100);
-  EventCountView* v3 = new EventCountView();
-  v3->SetBounds(0, 0, 50, 50);
-  EventCountView* v4 = new EventCountView();
-  v4->SetBounds(0, 0, 10, 10);
-  internal::RootView* root_view =
-      static_cast<internal::RootView*>(widget->GetRootView());
-  root_view->AddChildView(v1);
-  v1->AddChildView(v2);
-  v2->AddChildView(v3);
-  v3->AddChildView(v4);
-
-  widget->Show();
-
-  // |v1|, |v2|, and |v3| all handle gesture events but |v3| is marked as
-  // disabled.
-  v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
-  v2->set_handle_mode(EventCountView::CONSUME_EVENTS);
-  v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
-  v3->SetEnabled(false);
-
-  // No gesture handler is set in the root view. In this case the tap event
-  // should be dispatched only to |v4|, the gesture handler should be set to
-  // |v3|, and the event should be marked as handled.
-  GestureEventForTest tap(ui::ET_GESTURE_TAP, 5, 5);
-  widget->OnGestureEvent(&tap);
-  EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(v3, GetGestureHandler(root_view));
-  EXPECT_TRUE(tap.handled());
-  v1->ResetCounts();
-  v2->ResetCounts();
-  v3->ResetCounts();
-  v4->ResetCounts();
-
-  // A subsequent gesture event should be marked as handled but not dispatched.
-  tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
-  widget->OnGestureEvent(&tap);
-  EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(v3, GetGestureHandler(root_view));
-  EXPECT_TRUE(tap.handled());
-  v1->ResetCounts();
-  v2->ResetCounts();
-  v3->ResetCounts();
-  v4->ResetCounts();
-
-  // A GESTURE_END should reset the default gesture handler to NULL. It should
-  // also not be dispatched to |v3| but still marked as handled.
-  GestureEventForTest end(ui::ET_GESTURE_END, 5, 5);
-  widget->OnGestureEvent(&end);
-  EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(nullptr, GetGestureHandler(root_view));
-  EXPECT_TRUE(end.handled());
-  v1->ResetCounts();
-  v2->ResetCounts();
-  v3->ResetCounts();
-  v4->ResetCounts();
-
-  // Change the handle mode of |v3| to indicate that it would no longer like
-  // to handle events which are dispatched to it.
-  v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
-
-  // No gesture handler is set in the root view. In this case the tap event
-  // should be dispatched only to |v4| and the event should be marked as
-  // handled. Furthermore, the gesture handler should be set to
-  // |v3|; even though |v3| does not explicitly handle events, it is a
-  // valid target for the tap event because it is disabled.
-  tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
-  widget->OnGestureEvent(&tap);
-  EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
-  EXPECT_EQ(v3, GetGestureHandler(root_view));
-  EXPECT_TRUE(tap.handled());
-  v1->ResetCounts();
-  v2->ResetCounts();
-  v3->ResetCounts();
-  v4->ResetCounts();
-
-  // A GESTURE_END should reset the default gesture handler to NULL. It should
-  // also not be dispatched to |v3| but still marked as handled.
-  end = GestureEventForTest(ui::ET_GESTURE_END, 5, 5);
-  widget->OnGestureEvent(&end);
-  EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
-  EXPECT_EQ(nullptr, GetGestureHandler(root_view));
-  EXPECT_TRUE(end.handled());
-
-  widget->Close();
-}
-
 // Test the result of Widget::GetAllChildWidgets().
 TEST_F(WidgetTest, GetAllChildWidgets) {
   // Create the following widget hierarchy:
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h
index e85e78983..72efbf7e 100644
--- a/ui/views/window/dialog_delegate.h
+++ b/ui/views/window/dialog_delegate.h
@@ -125,17 +125,6 @@
   // DEPRECATED: use |set_accept_callback| instead.
   virtual bool Accept();
 
-  // Called when the user closes the window without selecting an option, e.g. by
-  // pressing the close button on the window, pressing the Esc key, or using a
-  // window manager gesture. By default, this calls Accept() if the only button
-  // in the dialog is Accept, Cancel() otherwise. This function should return
-  // true if the window can be closed after it returns, or false if it must
-  // remain open.
-  // DEPRECATED: use |set_close_callback| instead.
-  // NOTE: If **any** of the {accept,cancel,close} callbacks is set,
-  // DefaultClose() is not called and closing is unconditional.
-  virtual bool Close();
-
   // Overridden from WidgetDelegate:
   View* GetInitiallyFocusedView() override;
   DialogDelegate* AsDialogDelegate() override;
@@ -245,6 +234,10 @@
   void CancelDialog();
   void AcceptDialog();
 
+  // Deprecated, for compatibility with a few remaining unit tests.
+  // TODO(https://crbug.com/1011446): Delete this method.
+  bool Close();
+
   // Reset the dialog's shown timestamp, for tests that are subject to the
   // "unintended interaction" detection mechanism.
   void ResetViewShownTimeStampForTesting();
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc
index f79a48f..c07c6ac 100644
--- a/ui/views/window/dialog_delegate_unittest.cc
+++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -15,6 +15,7 @@
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/style/platform_style.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -48,19 +49,6 @@
   bool ShouldShowCloseButton() const override { return show_close_button_; }
 
   // DialogDelegateView overrides:
-  bool Cancel() override {
-    canceled_ = true;
-    return closeable_;
-  }
-  bool Accept() override {
-    accepted_ = true;
-    return closeable_;
-  }
-  bool Close() override {
-    closed_ = true;
-    return closeable_;
-  }
-
   gfx::Size CalculatePreferredSize() const override {
     return gfx::Size(200, 200);
   }
@@ -70,17 +58,7 @@
   base::string16 GetWindowTitle() const override { return title_; }
   View* GetInitiallyFocusedView() override { return input_; }
 
-  void CheckAndResetStates(bool canceled, bool accepted, bool closed) {
-    EXPECT_EQ(canceled, canceled_);
-    canceled_ = false;
-    EXPECT_EQ(accepted, accepted_);
-    accepted_ = false;
-    EXPECT_EQ(closed, closed_);
-    closed_ = false;
-  }
-
   void TearDown() {
-    closeable_ = true;
     GetWidget()->Close();
   }
 
@@ -96,11 +74,6 @@
 
  private:
   views::Textfield* input_;
-  bool canceled_ = false;
-  bool accepted_ = false;
-  bool closed_ = false;
-  // Prevent the dialog from closing, for repeated ok and cancel button clicks.
-  bool closeable_ = false;
   base::string16 title_;
   bool show_close_button_ = true;
   bool should_handle_escape_ = false;
@@ -142,6 +115,13 @@
 
     dialog_ = new TestDialog();
     dialog_->Init();
+
+    dialog_->set_accept_callback(
+        base::BindLambdaForTesting([&]() { accepted_ = true; }));
+    dialog_->set_cancel_callback(
+        base::BindLambdaForTesting([&]() { cancelled_ = true; }));
+    dialog_->set_close_callback(
+        base::BindLambdaForTesting([&]() { closed_ = true; }));
   }
 
   views::Widget* CreateDialogWidget(DialogDelegate* dialog) {
@@ -152,15 +132,20 @@
 
   void ShowDialog() { CreateDialogWidget(dialog_)->Show(); }
 
-  void SimulateKeyEvent(const ui::KeyEvent& event) {
-    ui::KeyEvent event_copy = event;
-    if (dialog()->GetFocusManager()->OnKeyEvent(event_copy))
-      dialog()->GetWidget()->OnKeyEvent(&event_copy);
+  void SimulateKeyPress(ui::KeyboardCode key) {
+    ui::KeyEvent event(ui::ET_KEY_PRESSED, key, ui::EF_NONE);
+    if (dialog()->GetFocusManager()->OnKeyEvent(event))
+      dialog()->GetWidget()->OnKeyEvent(&event);
   }
 
   TestDialog* dialog() const { return dialog_; }
   views::Widget* parent_widget() { return &parent_widget_; }
 
+ protected:
+  bool accepted_ = false;
+  bool cancelled_ = false;
+  bool closed_ = false;
+
  private:
   views::Widget parent_widget_;
   TestDialog* dialog_ = nullptr;
@@ -170,51 +155,69 @@
 
 }  // namespace
 
-TEST_F(DialogTest, AcceptAndCancel) {
-  LabelButton* ok_button = dialog()->GetOkButton();
-  LabelButton* cancel_button = dialog()->GetCancelButton();
-
-  // Check that return/escape accelerators accept/close dialogs.
+TEST_F(DialogTest, InputIsInitiallyFocused) {
   EXPECT_EQ(dialog()->input(), dialog()->GetFocusManager()->GetFocusedView());
+}
+
+TEST_F(DialogTest, OkButtonAccepts) {
+  EXPECT_FALSE(accepted_);
+  SimulateKeyPress(ui::VKEY_RETURN);
+  EXPECT_TRUE(accepted_);
+}
+
+TEST_F(DialogTest, EscButtonCloses) {
+  EXPECT_FALSE(closed_);
+  SimulateKeyPress(ui::VKEY_ESCAPE);
+  EXPECT_TRUE(closed_);
+}
+
+TEST_F(DialogTest, ReturnDirectedToOkButtonPlatformStyle) {
   const ui::KeyEvent return_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN,
                                   ui::EF_NONE);
-  SimulateKeyEvent(return_event);
-  dialog()->CheckAndResetStates(false, true, false);
-  const ui::KeyEvent escape_event(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE,
+  if (PlatformStyle::kReturnClicksFocusedControl) {
+    EXPECT_TRUE(dialog()->GetOkButton()->OnKeyPressed(return_event));
+    EXPECT_TRUE(accepted_);
+  } else {
+    EXPECT_FALSE(dialog()->GetOkButton()->OnKeyPressed(return_event));
+    EXPECT_FALSE(accepted_);
+    // If the return key press was not directed *specifically* to the Ok button,
+    // it would bubble upwards here, reach the dialog, and accept it. The
+    // OkButtonAccepts test above covers that behavior.
+  }
+}
+
+TEST_F(DialogTest, ReturnDirectedToCancelButtonPlatformBehavior) {
+  const ui::KeyEvent return_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN,
                                   ui::EF_NONE);
-  SimulateKeyEvent(escape_event);
-  dialog()->CheckAndResetStates(false, false, true);
+  if (PlatformStyle::kReturnClicksFocusedControl) {
+    EXPECT_TRUE(dialog()->GetCancelButton()->OnKeyPressed(return_event));
+    EXPECT_TRUE(cancelled_);
+  } else {
+    EXPECT_FALSE(dialog()->GetCancelButton()->OnKeyPressed(return_event));
+    EXPECT_FALSE(cancelled_);
+    // If the return key press was not directed *specifically* to the Ok button,
+    // it would bubble upwards here, reach the dialog, and accept it. The
+    // OkButtonAccepts test above covers that behavior.
+  }
+}
 
-// Check ok and cancel button behavior on a directed return key event. Buttons
-// won't respond to a return key event on Mac, since it performs the default
-// action.
-#if defined(OS_MACOSX)
-  EXPECT_FALSE(ok_button->OnKeyPressed(return_event));
-  dialog()->CheckAndResetStates(false, false, false);
-  EXPECT_FALSE(cancel_button->OnKeyPressed(return_event));
-  dialog()->CheckAndResetStates(false, false, false);
-#else
-  EXPECT_TRUE(ok_button->OnKeyPressed(return_event));
-  dialog()->CheckAndResetStates(false, true, false);
-  EXPECT_TRUE(cancel_button->OnKeyPressed(return_event));
-  dialog()->CheckAndResetStates(true, false, false);
-#endif
+// Unlike the previous two tests, this test simulates a key press at the level
+// of the dialog's Widget, so the return-to-close-dialog behavior does happen.
+TEST_F(DialogTest, ReturnOnCancelButtonPlatformBehavior) {
+  dialog()->GetCancelButton()->RequestFocus();
+  SimulateKeyPress(ui::VKEY_RETURN);
+  if (PlatformStyle::kReturnClicksFocusedControl) {
+    EXPECT_TRUE(cancelled_);
+  } else {
+    EXPECT_TRUE(accepted_);
+  }
+}
 
-  // Check that return accelerators cancel dialogs if cancel is focused, except
-  // on Mac where return should perform the default action.
-  cancel_button->RequestFocus();
-  EXPECT_EQ(cancel_button, dialog()->GetFocusManager()->GetFocusedView());
-  SimulateKeyEvent(return_event);
-#if defined(OS_MACOSX)
-  dialog()->CheckAndResetStates(false, true, false);
-#else
-  dialog()->CheckAndResetStates(true, false, false);
-#endif
-
-  // Check that escape can be overridden.
+TEST_F(DialogTest, CanOverrideEsc) {
   dialog()->set_should_handle_escape(true);
-  SimulateKeyEvent(escape_event);
-  dialog()->CheckAndResetStates(false, false, false);
+  SimulateKeyPress(ui::VKEY_ESCAPE);
+  EXPECT_FALSE(cancelled_);
+  EXPECT_FALSE(closed_);
 }
 
 TEST_F(DialogTest, RemoveDefaultButton) {
diff --git a/weblayer/browser/safe_browsing/safe_browsing_service.cc b/weblayer/browser/safe_browsing/safe_browsing_service.cc
index fbda32b..c699cd6 100644
--- a/weblayer/browser/safe_browsing/safe_browsing_service.cc
+++ b/weblayer/browser/safe_browsing/safe_browsing_service.cc
@@ -81,10 +81,11 @@
           },
           base::Unretained(this)),
       wc_getter, frame_tree_node_id,
-      // cache_manager and identity_manager are used to perform real time url
-      // check, which is gated by UKM opted in. Since WebLayer currently doesn't
-      // support UKM, this feature is not enabled.
-      /*cache_manager*/ nullptr, /*identity_manager*/ nullptr);
+      // cache_manager, identity_manager and rt_lookup_service are used to
+      // perform real time url check, which is gated by UKM opted in. Since
+      // WebLayer currently doesn't support UKM, this feature is not enabled.
+      /*cache_manager*/ nullptr, /*identity_manager*/ nullptr,
+      /*rt_lookup_service*/ nullptr);
 }
 
 std::unique_ptr<content::NavigationThrottle>