diff --git a/DEPS b/DEPS
index 71bb64a..5acc465 100644
--- a/DEPS
+++ b/DEPS
@@ -199,11 +199,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': '9acf5844cae6cd48bc106ea9bf5a2b337c8d1d33',
+  'skia_revision': '2d7afd4824c656b8c05810cff1751b430148fd8b',
   # 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': '72a5712edeff2f50384d4f57b2267ab41ed8b6f7',
+  'v8_revision': '9109ad2275ba3f77a6e611d593e5215c742ae589',
   # 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.
@@ -211,7 +211,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'cc5513855cc5bed41612c5cadd60f665e24ccce5',
+  'angle_revision': '5a4af4624777b0cd91d299eeeb13222414607f1b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -270,7 +270,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': '45fb1f2ebb99ec7146ad3f489831d9c39aa78f18',
+  'devtools_frontend_revision': '2bcf0b808628b338044bd296974437c96b96edb5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -318,11 +318,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'shaderc_revision': '5515d2a0c20cb73e68190b9a39445d4bea4eeeab',
+  'shaderc_revision': '28652ef368ef2e85e28ddc41bf69cc79705d4865',
   # 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': '450b6f4f844dab9417e54f08adf5b9d2ad30d1d7',
+  'dawn_revision': '7f4980e7d265d3f2e984dd316dccdb28a9dd86bf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -899,7 +899,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '233589f2e73f9cc1e4c759d93ab0565efc81ad36',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '320ceb93a21c7b5cee9d8cd95a282d06e1a3f6bd',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -950,7 +950,7 @@
     Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'e46493b9148e0d1e63f55b5890bff503822616e5',
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'f3cb1896971f449706bb1df5053d0e8fad6b0675',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'ae08b5b74c23a23f3b6c41e7266c1cd420cf4f77',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1252,7 +1252,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f50a0fb8a663da54c9424fc3ba54bec9ebdf962a',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '0997f358ce073f83d6a4bba44ffce2d772077577',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1330,7 +1330,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'bFZPJOh8GXPYKi1ZjDmJbS25G2gzmx-vLgGZ9Q4F82cC'
+              'version': '6w0qlJN7Xw7ZqAjvr5YYRHsrQ-LH90XaBZQZ8KvSHJAC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1480,7 +1480,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'd74c0e600a7f5bc43c2bcb75d4903b3038677459',
+    Var('webrtc_git') + '/src.git' + '@' + 'fc4668dae26e1c9ad40eb75919e7e733251fda4b',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1552,7 +1552,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@086c75fa39cf228f305c5689949c041d01634d92',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0d8628ddce9aa292a44a7207b3f782320f235ced',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
index 28eba7c5..eaa65e52 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -69,14 +69,12 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.ScopedSysTraceEvent;
-import org.chromium.base.task.PostTask;
 import org.chromium.components.autofill.AutofillProvider;
 import org.chromium.components.content_capture.ContentCaptureConsumerImpl;
 import org.chromium.components.content_capture.ContentCaptureFeatures;
 import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
 import org.chromium.content_public.browser.NavigationHistory;
 import org.chromium.content_public.browser.SmartClipProvider;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.url.GURL;
 
 import java.io.BufferedWriter;
@@ -2355,7 +2353,7 @@
     public void setBackgroundColor(final int color) {
         mFactory.startYourEngines(false);
         if (checkNeedsPost()) {
-            PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
                     setBackgroundColor(color);
@@ -2372,7 +2370,7 @@
         // is still null. We set the layer type in initForReal in that case.
         if (mAwContents == null) return;
         if (checkNeedsPost()) {
-            PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
                     setLayerType(layerType, paint);
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
index eddedc3..ba6cbfc 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
@@ -51,7 +51,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.ScopedSysTraceEvent;
 import org.chromium.base.task.PostTask;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
+import org.chromium.base.task.TaskTraits;
 import org.chromium.net.NetworkChangeNotifier;
 import org.chromium.ui.base.ResourceBundle;
 
@@ -457,7 +457,7 @@
     // Log extra information, for debugging purposes. Do the work asynchronously to avoid blocking
     // startup.
     private static void logCommandLineAndActiveTrials() {
-        PostTask.postTask(UiThreadTaskTraits.BEST_EFFORT, () -> {
+        PostTask.postTask(TaskTraits.BEST_EFFORT, () -> {
             // TODO(ntfschr): CommandLine can change at any time. For simplicity, only log it
             // once during startup.
             AwContentsStatics.logCommandLineForDebugging();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
index 3b3f04e..982869fa 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -647,7 +647,7 @@
             mTest.executeJavaScriptAndWaitForResult("document.getElementById('text2').select();");
             mTest.dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
             mCnt += mTest.waitForCallbackAndVerifyTypes(mCnt,
-                    new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED,
+                    new Integer[] {AUTOFILL_VIEW_EXITED, AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED,
                             AUTOFILL_SESSION_STARTED, AUTOFILL_VALUE_CHANGED});
         }
 
@@ -1126,7 +1126,7 @@
         executeJavaScriptAndWaitForResult("document.getElementById('text2').select();");
         dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
         waitForCallbackAndVerifyTypes(cnt,
-                new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED,
+                new Integer[] {AUTOFILL_VIEW_EXITED, AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED,
                         AUTOFILL_SESSION_STARTED, AUTOFILL_VALUE_CHANGED});
     }
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 5e947c3..9fe6cc5 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -396,6 +396,8 @@
     "frame/snap_controller_impl.cc",
     "frame/snap_controller_impl.h",
     "frame/wide_frame_view.cc",
+    "frame_throttler/frame_throttling_controller.cc",
+    "frame_throttler/frame_throttling_controller.h",
     "high_contrast/high_contrast_controller.cc",
     "high_contrast/high_contrast_controller.h",
     "highlighter/highlighter_controller.cc",
@@ -2434,6 +2436,7 @@
     "accessibility/test_accessibility_controller_client.h",
     "ambient/test/ambient_ash_test_base.cc",
     "ambient/test/ambient_ash_test_base.h",
+    "app_list/app_list_test_api.cc",
     "app_list/test/app_list_test_helper.cc",
     "app_list/test/app_list_test_helper.h",
     "app_list/test/test_app_list_client.cc",
@@ -2480,6 +2483,7 @@
     "metrics/task_switch_time_tracker_test_api.h",
     "metrics/user_metrics_recorder_test_api.cc",
     "metrics/user_metrics_recorder_test_api.h",
+    "public/cpp/test/app_list_test_api.h",
     "public/cpp/test/shell_test_api.h",
     "rotator/screen_rotation_animator_test_api.cc",
     "rotator/screen_rotation_animator_test_api.h",
diff --git a/ash/ambient/ambient_photo_controller.cc b/ash/ambient/ambient_photo_controller.cc
index 82f28bc..e36d143 100644
--- a/ash/ambient/ambient_photo_controller.cc
+++ b/ash/ambient/ambient_photo_controller.cc
@@ -40,6 +40,8 @@
 
 namespace {
 
+// TODO(b/161357364): refactor utility functions and constants
+
 // Topic related numbers.
 
 // The number of requests to fetch topics.
@@ -103,7 +105,6 @@
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
 }
 
-// TODO: Move to ambient_util.
 void WriteFile(const base::FilePath& path, const std::string& data) {
   if (!base::PathExists(GetRootPath()) &&
       !base::CreateDirectory(GetRootPath())) {
@@ -227,7 +228,7 @@
 AmbientPhotoController::~AmbientPhotoController() = default;
 
 void AmbientPhotoController::StartScreenUpdate() {
-  root_path_ = GetRootPath().Append(FILE_PATH_LITERAL(base::GenerateGUID()));
+  photo_path_ = GetRootPath().Append(FILE_PATH_LITERAL(base::GenerateGUID()));
   task_runner_->PostTaskAndReply(
       FROM_HERE, base::BindOnce(&DeletePathRecursively, GetRootPath()),
       base::BindOnce(&AmbientPhotoController::FetchTopics,
@@ -242,7 +243,8 @@
   weak_factory_.InvalidateWeakPtrs();
 
   task_runner_->PostTask(FROM_HERE,
-                         base::BindOnce(&DeletePathRecursively, root_path_));
+                         base::BindOnce(&DeletePathRecursively, photo_path_));
+  photo_path_.clear();
 }
 
 void AmbientPhotoController::OnTopicsChanged() {
@@ -320,7 +322,7 @@
   const AmbientModeTopic& topic = GetNextTopic();
   const std::string& image_url = topic.portrait_image_url.value_or(topic.url);
 
-  base::FilePath path = root_path_.Append(ToPhotoFileName(image_url));
+  base::FilePath path = photo_path_.Append(ToPhotoFileName(image_url));
   task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(
@@ -367,7 +369,7 @@
     return;
   }
 
-  const base::FilePath path = root_path_.Append(ToPhotoFileName(image_url));
+  const base::FilePath path = photo_path_.Append(ToPhotoFileName(image_url));
   task_runner_->PostTaskAndReply(
       FROM_HERE,
       base::BindOnce(
diff --git a/ash/ambient/ambient_photo_controller.h b/ash/ambient/ambient_photo_controller.h
index dea9dde..cac890b4 100644
--- a/ash/ambient/ambient_photo_controller.h
+++ b/ash/ambient/ambient_photo_controller.h
@@ -164,7 +164,7 @@
   ScopedObserver<AmbientBackendModel, AmbientBackendModelObserver>
       ambient_backend_model_observer_{this};
 
-  base::FilePath root_path_;
+  base::FilePath photo_path_;
 
   std::unique_ptr<AmbientURLLoader> url_loader_;
 
diff --git a/ash/ambient/ambient_photo_controller_unittest.cc b/ash/ambient/ambient_photo_controller_unittest.cc
index b877720..ce0babef 100644
--- a/ash/ambient/ambient_photo_controller_unittest.cc
+++ b/ash/ambient/ambient_photo_controller_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/base_paths.h"
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/hash/sha1.h"
@@ -104,26 +105,51 @@
   base::FilePath home_dir;
   base::PathService::Get(base::DIR_HOME, &home_dir);
 
-  // Start to refresh images.
-  photo_controller()->StartScreenUpdate();
-  base::FilePath root_path =
+  base::FilePath ambient_image_path =
       home_dir.Append(FILE_PATH_LITERAL(kAmbientModeDirectoryName));
-  EXPECT_TRUE(!base::PathExists(root_path) ||
-              base::IsDirectoryEmpty(root_path));
 
+  // Save a file to check if it gets deleted by StartScreenUpdate.
+  auto file_to_delete = ambient_image_path.Append("file_to_delete");
+  base::WriteFile(file_to_delete, "delete_me");
+
+  // Start to refresh images. Kicks off tasks that cleans |ambient_image_path|,
+  // then downloads a test image and writes it to a subdirectory of
+  // |ambient_image_path| in a delayed task.
+  photo_controller()->StartScreenUpdate();
   task_environment()->FastForwardBy(1.2 * kPhotoRefreshInterval);
+
+  EXPECT_TRUE(base::PathExists(ambient_image_path));
+  EXPECT_FALSE(base::PathExists(file_to_delete));
+
+  {
+    // Count files and directories in root_path. There should only be one
+    // subdirectory that was just created to save image files for this ambient
+    // mode session.
+    base::FileEnumerator files(
+        ambient_image_path, /*recursive=*/false,
+        base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
+    int count = 0;
+    for (base::FilePath current = files.Next(); !current.empty();
+         current = files.Next()) {
+      EXPECT_TRUE(files.GetInfo().IsDirectory());
+      count++;
+    }
+
+    EXPECT_EQ(count, 1);
+  }
+
   auto image = photo_controller()->ambient_backend_model()->GetNextImage();
   EXPECT_FALSE(image.isNull());
-  EXPECT_TRUE(base::PathExists(root_path));
-  EXPECT_FALSE(base::IsDirectoryEmpty(root_path));
 
   // Stop to refresh images.
   photo_controller()->StopScreenUpdate();
   task_environment()->FastForwardBy(1.2 * kPhotoRefreshInterval);
+
+  EXPECT_TRUE(base::PathExists(ambient_image_path));
+  EXPECT_TRUE(base::IsDirectoryEmpty(ambient_image_path));
+
   image = photo_controller()->ambient_backend_model()->GetNextImage();
   EXPECT_TRUE(image.isNull());
-  EXPECT_TRUE(base::PathExists(root_path));
-  EXPECT_TRUE(base::IsDirectoryEmpty(root_path));
 }
 
 }  // namespace ash
diff --git a/ash/ambient/test/ambient_ash_test_base.cc b/ash/ambient/test/ambient_ash_test_base.cc
index 5f2de2f..2934856 100644
--- a/ash/ambient/test/ambient_ash_test_base.cc
+++ b/ash/ambient/test/ambient_ash_test_base.cc
@@ -19,7 +19,9 @@
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
@@ -41,8 +43,9 @@
     auto data = std::make_unique<std::string>();
     *data = "test";
     // Pretend to respond asynchronously.
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), std::move(data)));
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE, base::BindOnce(std::move(callback), std::move(data)),
+        base::TimeDelta::FromMilliseconds(1));
   }
 };
 
diff --git a/ash/app_list/app_list_test_api.cc b/ash/app_list/app_list_test_api.cc
new file mode 100644
index 0000000..d4d2dd1
--- /dev/null
+++ b/ash/app_list/app_list_test_api.cc
@@ -0,0 +1,104 @@
+// 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/public/cpp/test/app_list_test_api.h"
+
+#include <string>
+#include <vector>
+
+#include "ash/app_list/app_list_controller_impl.h"
+#include "ash/app_list/model/app_list_folder_item.h"
+#include "ash/app_list/model/app_list_item.h"
+#include "ash/app_list/model/app_list_model.h"
+#include "ash/app_list/views/app_list_item_view.h"
+#include "ash/app_list/views/app_list_view.h"
+#include "ash/app_list/views/apps_grid_view.h"
+#include "ash/shell.h"
+#include "ui/views/view_model.h"
+
+namespace ash {
+
+AppListTestApi::AppListTestApi() = default;
+AppListTestApi::~AppListTestApi() = default;
+
+std::vector<std::string> AppListTestApi::GetTopLevelViewIdList() {
+  std::vector<std::string> id_list;
+  AppListView* app_list_view =
+      Shell::Get()->app_list_controller()->presenter()->GetView();
+  AppListView::TestApi test_api(app_list_view);
+  auto* view_model = test_api.GetRootAppsGridView()->view_model();
+  for (int i = 0; i < view_model->view_size(); ++i) {
+    AppListItem* app_list_item = view_model->view_at(i)->item();
+    if (app_list_item) {
+      id_list.push_back(app_list_item->id());
+    }
+  }
+  return id_list;
+}
+
+std::string AppListTestApi::CreateFolderWithApps(
+    const std::vector<std::string>& apps) {
+  // Only create a folder if there are two or more apps.
+  DCHECK_GE(apps.size(), 2u);
+
+  AppListModel* model = Shell::Get()->app_list_controller()->GetModel();
+  // Create a folder using the first two apps, and add the others to the folder
+  // iteratively.
+  std::string folder_id = model->MergeItems(apps[0], apps[1]);
+  // Return early if MergeItems failed.
+  if (folder_id.empty())
+    return "";
+  for (size_t i = 2; i < apps.size(); ++i)
+    model->MergeItems(folder_id, apps[i]);
+  return folder_id;
+}
+
+std::string AppListTestApi::GetFolderId(const std::string& app_id) {
+  return Shell::Get()
+      ->app_list_controller()
+      ->GetModel()
+      ->FindItem(app_id)
+      ->folder_id();
+}
+
+std::vector<std::string> AppListTestApi::GetAppIdsInFolder(
+    const std::string& folder_id) {
+  AppListItem* folder_item =
+      Shell::Get()->app_list_controller()->GetModel()->FindItem(folder_id);
+  DCHECK(folder_item->is_folder());
+  AppListItemList* folder_list =
+      static_cast<AppListFolderItem*>(folder_item)->item_list();
+  std::vector<std::string> id_list;
+  for (size_t i = 0; i < folder_list->item_count(); ++i)
+    id_list.push_back(folder_list->item_at(i)->id());
+  return id_list;
+}
+
+void AppListTestApi::MoveItemToPosition(const std::string& item_id,
+                                        const size_t to_index) {
+  AppListItem* app_item =
+      Shell::Get()->app_list_controller()->GetModel()->FindItem(item_id);
+  const std::string folder_id = app_item->folder_id();
+
+  AppListItemList* item_list;
+  std::vector<std::string> top_level_id_list = GetTopLevelViewIdList();
+  // The app should be either at the top level or in a folder.
+  if (folder_id.empty()) {
+    // The app is at the top level.
+    item_list =
+        Shell::Get()->app_list_controller()->GetModel()->top_level_item_list();
+  } else {
+    // The app is in the folder with |folder_id|.
+    item_list = Shell::Get()
+                    ->app_list_controller()
+                    ->GetModel()
+                    ->FindFolderItem(folder_id)
+                    ->item_list();
+  }
+  size_t from_index = 0;
+  item_list->FindItemIndex(item_id, &from_index);
+  item_list->MoveItem(from_index, to_index);
+}
+
+}  // namespace ash
diff --git a/ash/app_list/model/app_list_model.cc b/ash/app_list/model/app_list_model.cc
index 29f2a3c..633ee50d 100644
--- a/ash/app_list/model/app_list_model.cc
+++ b/ash/app_list/model/app_list_model.cc
@@ -16,12 +16,10 @@
 
 AppListModel::AppListModel()
     : top_level_item_list_(std::make_unique<AppListItemList>()) {
-  top_level_item_list_->AddObserver(this);
+  item_list_scoped_observer_.Add(top_level_item_list_.get());
 }
 
-AppListModel::~AppListModel() {
-  top_level_item_list_->RemoveObserver(this);
-}
+AppListModel::~AppListModel() = default;
 
 void AppListModel::AddObserver(AppListModelObserver* observer) {
   observers_.AddObserver(observer);
@@ -258,6 +256,10 @@
         << "Invalid call to DeleteItem for item with children: " << id;
     for (auto& observer : observers_)
       observer.OnAppListItemWillBeDeleted(item);
+    if (item->GetItemType() == AppListFolderItem::kItemType) {
+      item_list_scoped_observer_.Remove(
+          static_cast<AppListFolderItem*>(item)->item_list());
+    }
     top_level_item_list_->DeleteItem(id);
     for (auto& observer : observers_)
       observer.OnAppListItemDeleted(id);
@@ -335,6 +337,10 @@
 AppListItem* AppListModel::AddItemToItemListAndNotify(
     std::unique_ptr<AppListItem> item_ptr) {
   DCHECK(!item_ptr->IsInFolder());
+  if (item_ptr->GetItemType() == AppListFolderItem::kItemType) {
+    item_list_scoped_observer_.Add(
+        static_cast<AppListFolderItem*>(item_ptr.get())->item_list());
+  }
   AppListItem* item = top_level_item_list_->AddItem(std::move(item_ptr));
   for (auto& observer : observers_)
     observer.OnAppListItemAdded(item);
diff --git a/ash/app_list/model/app_list_model.h b/ash/app_list/model/app_list_model.h
index cf153c9..12aa8d4 100644
--- a/ash/app_list/model/app_list_model.h
+++ b/ash/app_list/model/app_list_model.h
@@ -17,6 +17,7 @@
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "base/scoped_observer.h"
 
 namespace ash {
 
@@ -164,7 +165,8 @@
   // The AppListView state. Controlled by the AppListView.
   AppListViewState state_fullscreen_ = AppListViewState::kClosed;
   base::ObserverList<AppListModelObserver, true>::Unchecked observers_;
-
+  ScopedObserver<AppListItemList, AppListItemListObserver>
+      item_list_scoped_observer_{this};
   DISALLOW_COPY_AND_ASSIGN(AppListModel);
 };
 
diff --git a/ash/app_list/views/assistant/assistant_page_view_unittest.cc b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
index 38f620b..1835655a 100644
--- a/ash/app_list/views/assistant/assistant_page_view_unittest.cc
+++ b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
@@ -6,6 +6,7 @@
 #include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/assistant/test/assistant_ash_test_base.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
+#include "ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h"
 #include "ash/assistant/ui/main_stage/suggestion_chip_view.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/run_loop.h"
@@ -377,6 +378,47 @@
   } while (focused_view != initial_focused_view);
 }
 
+TEST_F(AssistantPageViewTest,
+       FocusShouldCycleThroughOnboardingSuggestionsWhenPressingTab) {
+  constexpr int kMaxIterations = 100;
+
+  // Enable the |kAssistantBetterOnboarding| feature and change onboarding mode
+  // to force suggestion generation. We have to force suggestion generation in
+  // this way since the feature wasn't enabled prior to controller creation.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      chromeos::assistant::features::kAssistantBetterOnboarding);
+  SetOnboardingMode(AssistantOnboardingMode::kEducation);
+
+  // Show Assistant UI and verify onboarding suggestions exist.
+  ShowAssistantUi();
+  auto onboarding_suggestions = GetOnboardingSuggestionViews();
+  ASSERT_FALSE(onboarding_suggestions.empty());
+
+  // Cache the first focused view.
+  auto* first_focused_view = GetFocusedView();
+
+  // Advance focus to the first onboarding suggestion.
+  int num_iterations = 0;
+  while (GetFocusedView() != onboarding_suggestions.at(0)) {
+    PressKeyAndWait(ui::VKEY_TAB);
+    ASSERT_LE(++num_iterations, kMaxIterations);  // Sanity check.
+  }
+
+  // Verify we can cycle through them.
+  for (size_t i = 0; i < onboarding_suggestions.size(); ++i) {
+    ASSERT_EQ(GetFocusedView(), onboarding_suggestions.at(i));
+    PressKeyAndWait(ui::VKEY_TAB);
+  }
+
+  // Confirm that we eventually get back to our first focused view.
+  num_iterations = 0;
+  while (GetFocusedView() != first_focused_view) {
+    PressKeyAndWait(ui::VKEY_TAB);
+    ASSERT_LE(++num_iterations, kMaxIterations);  // Sanity check.
+  }
+}
+
 TEST_F(AssistantPageViewTest, ShouldFocusMicWhenOpeningWithHotword) {
   ShowAssistantUi(AssistantEntryPoint::kHotword);
 
diff --git a/ash/assistant/test/assistant_ash_test_base.cc b/ash/assistant/test/assistant_ash_test_base.cc
index 1cb7c4d..d892cb4 100644
--- a/ash/assistant/test/assistant_ash_test_base.cc
+++ b/ash/assistant/test/assistant_ash_test_base.cc
@@ -11,6 +11,7 @@
 #include "ash/assistant/test/test_assistant_client.h"
 #include "ash/assistant/test/test_assistant_setup.h"
 #include "ash/assistant/test/test_assistant_web_view_factory.h"
+#include "ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h"
 #include "ash/assistant/ui/main_stage/suggestion_chip_view.h"
 #include "ash/keyboard/ui/keyboard_ui_controller.h"
 #include "ash/keyboard/ui/test/keyboard_test_util.h"
@@ -302,10 +303,15 @@
   return test_api_->suggestion_chip_container();
 }
 
-std::vector<ash::SuggestionChipView*>
-AssistantAshTestBase::GetSuggestionChips() {
+std::vector<AssistantOnboardingSuggestionView*>
+AssistantAshTestBase::GetOnboardingSuggestionViews() {
+  const views::View* container = onboarding_view();
+  return ChildViewCollector<AssistantOnboardingSuggestionView>{container}.Get();
+}
+
+std::vector<SuggestionChipView*> AssistantAshTestBase::GetSuggestionChips() {
   const views::View* container = suggestion_chip_container();
-  return ChildViewCollector<ash::SuggestionChipView>{container}.Get();
+  return ChildViewCollector<SuggestionChipView>{container}.Get();
 }
 
 void AssistantAshTestBase::ShowKeyboard() {
diff --git a/ash/assistant/test/assistant_ash_test_base.h b/ash/assistant/test/assistant_ash_test_base.h
index 0359c15..c2901fb 100644
--- a/ash/assistant/test/assistant_ash_test_base.h
+++ b/ash/assistant/test/assistant_ash_test_base.h
@@ -28,6 +28,7 @@
 namespace ash {
 
 class AppListView;
+class AssistantOnboardingSuggestionView;
 class AssistantTestApi;
 class SuggestionChipView;
 class TestAssistantClient;
@@ -171,8 +172,12 @@
   // Return the container with all the suggestion chips.
   views::View* suggestion_chip_container();
 
+  // Return the onboarding suggestions that are currently displayed.
+  std::vector<AssistantOnboardingSuggestionView*>
+  GetOnboardingSuggestionViews();
+
   // Return the suggestion chips that are currently displayed.
-  std::vector<ash::SuggestionChipView*> GetSuggestionChips();
+  std::vector<SuggestionChipView*> GetSuggestionChips();
 
   // Show/Dismiss the on-screen keyboard.
   void ShowKeyboard();
diff --git a/ash/assistant/ui/BUILD.gn b/ash/assistant/ui/BUILD.gn
index e2251e6..ee005b3 100644
--- a/ash/assistant/ui/BUILD.gn
+++ b/ash/assistant/ui/BUILD.gn
@@ -56,6 +56,8 @@
     "main_stage/assistant_error_element_view.h",
     "main_stage/assistant_footer_view.cc",
     "main_stage/assistant_footer_view.h",
+    "main_stage/assistant_onboarding_suggestion_view.cc",
+    "main_stage/assistant_onboarding_suggestion_view.h",
     "main_stage/assistant_onboarding_view.cc",
     "main_stage/assistant_onboarding_view.h",
     "main_stage/assistant_opt_in_view.cc",
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.cc b/ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.cc
new file mode 100644
index 0000000..6e67c2b
--- /dev/null
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.cc
@@ -0,0 +1,181 @@
+// 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/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h"
+
+#include "ash/assistant/ui/assistant_ui_constants.h"
+#include "ash/assistant/ui/assistant_view_delegate.h"
+#include "ash/assistant/util/resource_util.h"
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chromeos/services/assistant/public/cpp/assistant_service.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/highlight_path_generator.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/flex_layout.h"
+#include "ui/views/view_class_properties.h"
+
+namespace ash {
+
+namespace {
+
+using assistant::util::ResourceLinkType;
+
+// Appearance.
+constexpr int kCornerRadiusDip = 12;
+constexpr int kIconSizeDip = 24;
+constexpr int kLabelLineHeight = 20;
+constexpr int kLabelSizeDelta = 2;
+constexpr int kPreferredHeightDip = 72;
+
+// Helpers ---------------------------------------------------------------------
+
+SkColor GetSuggestionBackgroundColor(int index) {
+  constexpr SkColor kBackgroundColors[] = {gfx::kGoogleBlue050,
+                                           gfx::kGoogleRed050,
+                                           gfx::kGoogleYellow050,
+                                           gfx::kGoogleGreen050,
+                                           SkColorSetRGB(0xF6, 0xE9, 0xF8),
+                                           gfx::kGoogleBlue050};
+  DCHECK_GE(index, 0);
+  DCHECK_LT(index, static_cast<int>(base::size(kBackgroundColors)));
+  return kBackgroundColors[index];
+}
+
+SkColor GetSuggestionForegroundColor(int index) {
+  constexpr SkColor kForegroundColors[] = {gfx::kGoogleBlue800,
+                                           gfx::kGoogleRed800,
+                                           SkColorSetRGB(0xBF, 0x50, 0x00),
+                                           gfx::kGoogleGreen800,
+                                           SkColorSetRGB(0x8A, 0x0E, 0x9E),
+                                           gfx::kGoogleBlue800};
+  DCHECK_GE(index, 0);
+  DCHECK_LT(index, static_cast<int>(base::size(kForegroundColors)));
+  return kForegroundColors[index];
+}
+
+}  // namespace
+
+// AssistantOnboardingSuggestionView -------------------------------------------
+
+// static
+constexpr char AssistantOnboardingSuggestionView::kClassName[];
+
+AssistantOnboardingSuggestionView::AssistantOnboardingSuggestionView(
+    AssistantViewDelegate* delegate,
+    const chromeos::assistant::AssistantSuggestion& suggestion,
+    int index)
+    : views::Button(this),
+      delegate_(delegate),
+      suggestion_id_(suggestion.id),
+      index_(index) {
+  InitLayout(suggestion);
+}
+
+AssistantOnboardingSuggestionView::~AssistantOnboardingSuggestionView() =
+    default;
+
+const char* AssistantOnboardingSuggestionView::GetClassName() const {
+  return kClassName;
+}
+
+int AssistantOnboardingSuggestionView::GetHeightForWidth(int width) const {
+  return kPreferredHeightDip;
+}
+
+void AssistantOnboardingSuggestionView::ChildPreferredSizeChanged(
+    views::View* child) {
+  PreferredSizeChanged();
+}
+
+void AssistantOnboardingSuggestionView::ButtonPressed(views::Button* sender,
+                                                      const ui::Event& event) {
+  delegate_->OnSuggestionPressed(suggestion_id_);
+}
+
+const gfx::ImageSkia& AssistantOnboardingSuggestionView::GetIcon() const {
+  return icon_->GetImage();
+}
+
+const base::string16& AssistantOnboardingSuggestionView::GetText() const {
+  return label_->GetText();
+}
+
+void AssistantOnboardingSuggestionView::InitLayout(
+    const chromeos::assistant::AssistantSuggestion& suggestion) {
+  // A11y.
+  SetAccessibleName(base::UTF8ToUTF16(suggestion.text));
+
+  // Background.
+  SetBackground(views::CreateRoundedRectBackground(
+      GetSuggestionBackgroundColor(index_), kCornerRadiusDip));
+
+  // Focus.
+  SetFocusBehavior(FocusBehavior::ALWAYS);
+  focus_ring()->SetColor(gfx::kGoogleBlue300);
+  focus_ring()->SetPathGenerator(
+      std::make_unique<views::RoundRectHighlightPathGenerator>(
+          gfx::Insets(), kCornerRadiusDip));
+
+  // Layout.
+  auto& layout =
+      SetLayoutManager(std::make_unique<views::FlexLayout>())
+          ->SetCollapseMargins(true)
+          .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
+          .SetDefault(views::kFlexBehaviorKey, views::FlexSpecification())
+          .SetDefault(views::kMarginsKey, gfx::Insets(0, 2 * kSpacingDip))
+          .SetInteriorMargin(gfx::Insets(0, 2 * kMarginDip))
+          .SetOrientation(views::LayoutOrientation::kHorizontal);
+
+  // NOTE: Our |layout| ignores the view for drawing focus as it is a special
+  // view which lays out itself. Removing this would cause it *not* to paint.
+  layout.SetChildViewIgnoredByLayout(focus_ring(), true);
+
+  // Icon.
+  icon_ = AddChildView(std::make_unique<views::ImageView>());
+  icon_->SetImageSize({kIconSizeDip, kIconSizeDip});
+  icon_->SetPreferredSize({kIconSizeDip, kIconSizeDip});
+
+  const GURL& url = suggestion.icon_url;
+  if (assistant::util::IsResourceLinkType(url, ResourceLinkType::kIcon)) {
+    // Handle local images.
+    icon_->SetImage(assistant::util::CreateVectorIcon(
+        assistant::util::AppendOrReplaceColorParam(
+            url, GetSuggestionForegroundColor(index_)),
+        kIconSizeDip));
+  } else if (url.is_valid()) {
+    // Handle remote images.
+    delegate_->DownloadImage(
+        url, base::BindOnce(&AssistantOnboardingSuggestionView::UpdateIcon,
+                            weak_factory_.GetWeakPtr()));
+  }
+
+  // Label.
+  label_ = AddChildView(std::make_unique<views::Label>());
+  label_->SetAutoColorReadabilityEnabled(false);
+  label_->SetEnabledColor(GetSuggestionForegroundColor(index_));
+  label_->SetFontList(assistant::ui::GetDefaultFontList()
+                          .DeriveWithSizeDelta(kLabelSizeDelta)
+                          .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
+  label_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
+  label_->SetLineHeight(kLabelLineHeight);
+  label_->SetMaxLines(2);
+  label_->SetMultiLine(true);
+  label_->SetPreferredSize(gfx::Size(INT_MAX, INT_MAX));
+  label_->SetProperty(
+      views::kFlexBehaviorKey,
+      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
+                               views::MaximumFlexSizeRule::kUnbounded,
+                               /*adjust_height_for_width=*/true));
+  label_->SetText(base::UTF8ToUTF16(suggestion.text));
+}
+
+void AssistantOnboardingSuggestionView::UpdateIcon(const gfx::ImageSkia& icon) {
+  if (!icon.isNull())
+    icon_->SetImage(icon);
+}
+
+}  // namespace ash
\ No newline at end of file
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h b/ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h
new file mode 100644
index 0000000..294a4d4
--- /dev/null
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h
@@ -0,0 +1,74 @@
+// 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_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_ONBOARDING_SUGGESTION_VIEW_H_
+#define ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_ONBOARDING_SUGGESTION_VIEW_H_
+
+#include "base/component_export.h"
+#include "base/unguessable_token.h"
+#include "ui/views/controls/button/button.h"
+
+namespace chromeos {
+namespace assistant {
+struct AssistantSuggestion;
+}  // namespace assistant
+}  // namespace chromeos
+
+namespace views {
+class ImageView;
+class Label;
+}  // namespace views
+
+namespace ash {
+
+class AssistantViewDelegate;
+
+class COMPONENT_EXPORT(ASSISTANT_UI) AssistantOnboardingSuggestionView
+    : public views::Button,
+      public views::ButtonListener {
+ public:
+  static constexpr char kClassName[] = "AssistantOnboardingSuggestionView";
+
+  AssistantOnboardingSuggestionView(
+      AssistantViewDelegate* delegate,
+      const chromeos::assistant::AssistantSuggestion& suggestion,
+      int index);
+
+  AssistantOnboardingSuggestionView(const AssistantOnboardingSuggestionView&) =
+      delete;
+  AssistantOnboardingSuggestionView& operator=(
+      const AssistantOnboardingSuggestionView&) = delete;
+  ~AssistantOnboardingSuggestionView() override;
+
+  // views::View:
+  const char* GetClassName() const override;
+  int GetHeightForWidth(int width) const override;
+  void ChildPreferredSizeChanged(views::View* child) override;
+
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+  // Returns the icon for the suggestion.
+  const gfx::ImageSkia& GetIcon() const;
+
+  // Returns the text for the suggestion.
+  const base::string16& GetText() const;
+
+ private:
+  void InitLayout(const chromeos::assistant::AssistantSuggestion& suggestion);
+  void UpdateIcon(const gfx::ImageSkia& icon);
+
+  AssistantViewDelegate* const delegate_;  // Owned by AssistantController.
+  const base::UnguessableToken suggestion_id_;
+  const int index_;
+
+  views::ImageView* icon_ = nullptr;  // Owned by view hierarchy.
+  views::Label* label_ = nullptr;     // Owned by view hierarchy.
+
+  base::WeakPtrFactory<AssistantOnboardingSuggestionView> weak_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_ONBOARDING_SUGGESTION_VIEW_H_
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_view.cc b/ash/assistant/ui/main_stage/assistant_onboarding_view.cc
index 2cd0c1d..8c0118e 100644
--- a/ash/assistant/ui/main_stage/assistant_onboarding_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_view.cc
@@ -14,7 +14,7 @@
 #include "ash/assistant/ui/assistant_ui_constants.h"
 #include "ash/assistant/ui/assistant_view_delegate.h"
 #include "ash/assistant/ui/assistant_view_ids.h"
-#include "ash/assistant/util/resource_util.h"
+#include "ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h"
 #include "ash/public/cpp/assistant/controller/assistant_suggestions_controller.h"
 #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -25,19 +25,15 @@
 #include "ui/gfx/color_palette.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
-#include "ui/views/controls/button/button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/grid_layout.h"
-#include "ui/views/view_class_properties.h"
 
 namespace ash {
 
 namespace {
 
-using assistant::util::ResourceLinkType;
 using chromeos::assistant::AssistantSuggestion;
 using chromeos::assistant::AssistantSuggestionType;
 
@@ -53,16 +49,9 @@
 // Suggestions.
 constexpr int kSuggestionsColumnCount = 3;
 constexpr int kSuggestionsColumnSetId = 1;
-constexpr int kSuggestionsCornerRadiusDip = 12;
-constexpr int kSuggestionsIconSizeDip = 24;
-constexpr int kSuggestionsLabelLineHeight = 20;
-constexpr int kSuggestionsLabelSizeDelta = 2;
 constexpr int kSuggestionsMaxCount = 6;
 constexpr int kSuggestionsMarginDip = 16;
 constexpr int kSuggestionsMarginTopDip = 32;
-constexpr int kSuggestionsPaddingDip = 16;
-constexpr int kSuggestionsPreferredHeightDip = 72;
-constexpr int kSuggestionsSpacingDip = 16;
 
 // Helpers ---------------------------------------------------------------------
 
@@ -99,135 +88,6 @@
       base::UTF8ToUTF16(delegate->GetPrimaryUserGivenName()));
 }
 
-SkColor GetSuggestionBackgroundColor(int index) {
-  DCHECK_GE(index, 0);
-  DCHECK_LT(index, kSuggestionsMaxCount);
-  constexpr SkColor background_colors[kSuggestionsMaxCount] = {
-      gfx::kGoogleBlue050,
-      gfx::kGoogleRed050,
-      gfx::kGoogleYellow050,
-      gfx::kGoogleGreen050,
-      SkColorSetRGB(0xF6, 0xE9, 0xF8),
-      gfx::kGoogleBlue050};
-  return background_colors[index];
-}
-
-SkColor GetSuggestionForegroundColor(int index) {
-  DCHECK_GE(index, 0);
-  DCHECK_LT(index, kSuggestionsMaxCount);
-  constexpr SkColor foreground_colors[kSuggestionsMaxCount] = {
-      gfx::kGoogleBlue800,
-      gfx::kGoogleRed800,
-      SkColorSetRGB(0xBF, 0x50, 0x00),
-      gfx::kGoogleGreen800,
-      SkColorSetRGB(0x8A, 0x0E, 0x9E),
-      gfx::kGoogleBlue800};
-  return foreground_colors[index];
-}
-
-// SuggestionView --------------------------------------------------------------
-
-class SuggestionView : public views::Button, public views::ButtonListener {
- public:
-  SuggestionView(AssistantViewDelegate* delegate,
-                 const AssistantSuggestion& suggestion,
-                 int index)
-      : views::Button(this),
-        delegate_(delegate),
-        suggestion_id_(suggestion.id),
-        index_(index) {
-    InitLayout(suggestion);
-  }
-
-  SuggestionView(const SuggestionView&) = delete;
-  SuggestionView& operator=(const SuggestionView&) = delete;
-  ~SuggestionView() override = default;
-
-  // views::Button:
-  const char* GetClassName() const override { return "SuggestionView"; }
-
-  int GetHeightForWidth(int width) const override {
-    return kSuggestionsPreferredHeightDip;
-  }
-
-  void ChildPreferredSizeChanged(views::View* child) override {
-    PreferredSizeChanged();
-  }
-
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override {
-    delegate_->OnSuggestionPressed(suggestion_id_);
-  }
-
- private:
-  void InitLayout(const AssistantSuggestion& suggestion) {
-    // Background.
-    SetBackground(views::CreateRoundedRectBackground(
-        GetSuggestionBackgroundColor(index_), kSuggestionsCornerRadiusDip));
-
-    // Layout.
-    SetLayoutManager(std::make_unique<views::FlexLayout>())
-        ->SetCollapseMargins(true)
-        .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
-        .SetDefault(views::kFlexBehaviorKey, views::FlexSpecification())
-        .SetDefault(views::kMarginsKey, gfx::Insets(0, kSuggestionsSpacingDip))
-        .SetInteriorMargin(gfx::Insets(0, kSuggestionsPaddingDip))
-        .SetOrientation(views::LayoutOrientation::kHorizontal);
-
-    // Icon.
-    icon_ = AddChildView(std::make_unique<views::ImageView>());
-    icon_->SetImageSize({kSuggestionsIconSizeDip, kSuggestionsIconSizeDip});
-    icon_->SetPreferredSize({kSuggestionsIconSizeDip, kSuggestionsIconSizeDip});
-
-    const GURL& url = suggestion.icon_url;
-    if (assistant::util::IsResourceLinkType(url, ResourceLinkType::kIcon)) {
-      // Handle local images.
-      icon_->SetImage(assistant::util::CreateVectorIcon(
-          assistant::util::AppendOrReplaceColorParam(
-              url, GetSuggestionForegroundColor(index_)),
-          kSuggestionsIconSizeDip));
-    } else if (url.is_valid()) {
-      // Handle remote images.
-      delegate_->DownloadImage(url,
-                               base::BindOnce(&SuggestionView::OnIconDownloaded,
-                                              weak_factory_.GetWeakPtr()));
-    }
-
-    // Label.
-    label_ = AddChildView(std::make_unique<views::Label>());
-    label_->SetAutoColorReadabilityEnabled(false);
-    label_->SetEnabledColor(GetSuggestionForegroundColor(index_));
-    label_->SetFontList(assistant::ui::GetDefaultFontList()
-                            .DeriveWithSizeDelta(kSuggestionsLabelSizeDelta)
-                            .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
-    label_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
-    label_->SetLineHeight(kSuggestionsLabelLineHeight);
-    label_->SetMaxLines(2);
-    label_->SetMultiLine(true);
-    label_->SetPreferredSize(gfx::Size(INT_MAX, INT_MAX));
-    label_->SetProperty(
-        views::kFlexBehaviorKey,
-        views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
-                                 views::MaximumFlexSizeRule::kUnbounded,
-                                 /*adjust_height_for_width=*/true));
-    label_->SetText(base::UTF8ToUTF16(suggestion.text));
-  }
-
-  void OnIconDownloaded(const gfx::ImageSkia& icon) {
-    if (!icon.isNull())
-      icon_->SetImage(icon);
-  }
-
-  AssistantViewDelegate* const delegate_;
-  const base::UnguessableToken suggestion_id_;
-  const int index_;
-
-  views::ImageView* icon_;  // Owned by view hierarchy.
-  views::Label* label_;     // Owned by view hierarchy.
-
-  base::WeakPtrFactory<SuggestionView> weak_factory_{this};
-};
-
 }  // namespace
 
 // AssistantOnboardingView -----------------------------------------------------
@@ -363,8 +223,8 @@
                          /*column_set_id=*/kSuggestionsColumnSetId);
       }
     }
-    layout->AddView(
-        std::make_unique<SuggestionView>(delegate_, suggestions.at(i), i));
+    layout->AddView(std::make_unique<AssistantOnboardingSuggestionView>(
+        delegate_, suggestions.at(i), i));
   }
 }
 
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc b/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
index e7b8007..35e3bf4e 100644
--- a/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/assistant/model/assistant_suggestions_model.h"
 #include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/assistant/test/assistant_ash_test_base.h"
+#include "ash/assistant/ui/main_stage/assistant_onboarding_suggestion_view.h"
 #include "ash/assistant/ui/test_support/mock_assistant_view_delegate.h"
 #include "ash/assistant/util/test_support/macros.h"
 #include "ash/public/cpp/assistant/controller/assistant_suggestions_controller.h"
@@ -63,7 +64,7 @@
     auto* candidate = children.front();
     children.pop();
 
-    if (candidate->GetClassName() == T::kViewClassName) {
+    if (candidate->GetClassName() == T::kClassName) {
       *result = static_cast<T*>(candidate);
       return;
     }
@@ -157,10 +158,6 @@
     return static_cast<views::Label*>(onboarding_view()->children().at(1));
   }
 
-  views::View* suggestions_grid() {
-    return onboarding_view()->children().at(2);
-  }
-
  private:
   base::test::ScopedRestoreICUDefaultLocale locale_{"en_US"};
   base::test::ScopedFeatureList feature_list_;
@@ -343,27 +340,22 @@
         break;
     }
 
-    // Show Assistant UI and verify the expected number of suggestion views.
     ShowAssistantUi();
-    ASSERT_EQ(suggestions_grid()->children().size(),
-              expected_suggestions.size());
+
+    // Verify the expected number of suggestion views.
+    auto suggestion_views = GetOnboardingSuggestionViews();
+    ASSERT_EQ(suggestion_views.size(), expected_suggestions.size());
 
     // Verify that each suggestion view has the expected message and icon.
     for (size_t i = 0; i < expected_suggestions.size(); ++i) {
-      auto* suggestion_view = suggestions_grid()->children().at(i);
+      const auto* suggestion_view = suggestion_views.at(i);
       const auto& expected_suggestion = expected_suggestions.at(i);
 
-      views::Label* label = nullptr;
-      FindDescendentByClassName(suggestion_view, &label);
-      ASSERT_NE(label, nullptr);
-      EXPECT_EQ(label->GetText(),
+      EXPECT_EQ(suggestion_view->GetText(),
                 base::UTF8ToUTF16(expected_suggestion.message));
 
-      views::ImageView* icon = nullptr;
-      FindDescendentByClassName(suggestion_view, &icon);
-      ASSERT_NE(icon, nullptr);
       ASSERT_PIXELS_EQ(
-          icon->GetImage(),
+          suggestion_view->GetIcon(),
           gfx::CreateVectorIcon(expected_suggestion.icon_with_color->icon,
                                 /*size=*/24,
                                 expected_suggestion.icon_with_color->color));
@@ -372,9 +364,11 @@
 }
 
 TEST_F(AssistantOnboardingViewTest, ShouldHandleSuggestionPresses) {
-  // Show Assistant UI and verify onboarding suggestions exist.
   ShowAssistantUi();
-  ASSERT_FALSE(suggestions_grid()->children().empty());
+
+  // Verify onboarding suggestions exist.
+  auto suggestion_views = GetOnboardingSuggestionViews();
+  ASSERT_FALSE(suggestion_views.empty());
 
   // Expect a text interaction originating from the onboarding feature...
   MockAssistantInteractionSubscriber subscriber(assistant_service());
@@ -386,13 +380,13 @@
           }));
 
   // ...when an onboarding suggestion is pressed.
-  TapOnAndWait(suggestions_grid()->children().at(0));
+  TapOnAndWait(suggestion_views.at(0));
 }
 
 TEST_F(AssistantOnboardingViewTest, ShouldHandleSuggestionUpdates) {
   // Show Assistant UI and verify suggestions exist.
   ShowAssistantUi();
-  EXPECT_FALSE(suggestions_grid()->children().empty());
+  ASSERT_FALSE(GetOnboardingSuggestionViews().empty());
 
   // Manually create a suggestion.
   AssistantSuggestion suggestion;
@@ -406,27 +400,21 @@
   SetOnboardingSuggestions(std::move(suggestions));
 
   // Verify view state is updated to reflect model state.
-  ASSERT_EQ(suggestions_grid()->children().size(), 1u);
-  views::Label* label = nullptr;
-  FindDescendentByClassName(suggestions_grid()->children().at(0), &label);
-  ASSERT_NE(nullptr, label);
-  EXPECT_EQ(label->GetText(), base::UTF8ToUTF16("Forced suggestion"));
+  auto suggestion_views = GetOnboardingSuggestionViews();
+  ASSERT_EQ(suggestion_views.size(), 1u);
+  EXPECT_EQ(suggestion_views.at(0)->GetText(),
+            base::UTF8ToUTF16("Forced suggestion"));
 }
 
 TEST_F(AssistantOnboardingViewTest, ShouldHandleLocalIcons) {
-  MockAssistantViewDelegate delegate;
-  EXPECT_CALL(delegate, GetPrimaryUserGivenName)
-      .WillOnce(testing::Return("Primary User Given Name"));
-
-  AssistantOnboardingView onboarding_view(&delegate);
   SetOnboardingSuggestions({CreateSuggestionWithIconUrl(
       "googleassistant://resource?type=icon&name=assistant")});
 
-  views::ImageView* icon_view = nullptr;
-  FindDescendentByClassName(&onboarding_view, &icon_view);
-  ASSERT_NE(nullptr, icon_view);
+  ShowAssistantUi();
+  auto suggestion_views = GetOnboardingSuggestionViews();
+  ASSERT_EQ(suggestion_views.size(), 1u);
 
-  const auto& actual = icon_view->GetImage();
+  const auto& actual = suggestion_views.at(0)->GetIcon();
   gfx::ImageSkia expected = gfx::CreateVectorIcon(
       gfx::IconDescription(ash::kAssistantIcon, /*size=*/24));
 
@@ -451,11 +439,11 @@
   SetOnboardingSuggestions({CreateSuggestionWithIconUrl(
       "https://www.gstatic.com/images/branding/product/2x/googleg_48dp.png")});
 
-  views::ImageView* icon_view = nullptr;
-  FindDescendentByClassName(&onboarding_view, &icon_view);
-  ASSERT_NE(nullptr, icon_view);
+  AssistantOnboardingSuggestionView* suggestion_view = nullptr;
+  FindDescendentByClassName(&onboarding_view, &suggestion_view);
+  ASSERT_NE(nullptr, suggestion_view);
 
-  const auto& actual = icon_view->GetImage();
+  const auto& actual = suggestion_view->GetIcon();
   EXPECT_TRUE(actual.BackedBySameObjectAs(expected));
 }
 
diff --git a/ash/frame_throttler/frame_throttling_controller.cc b/ash/frame_throttler/frame_throttling_controller.cc
new file mode 100644
index 0000000..20f1c95c
--- /dev/null
+++ b/ash/frame_throttler/frame_throttling_controller.cc
@@ -0,0 +1,72 @@
+// 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/frame_throttler/frame_throttling_controller.h"
+#include "ash/public/cpp/app_types.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/host/host_frame_sink_manager.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
+
+namespace ash {
+
+namespace {
+
+void CollectFrameSinkIds(const aura::Window* window,
+                         std::vector<viz::FrameSinkId>* frame_sink_ids) {
+  if (window->GetFrameSinkId().is_valid()) {
+    frame_sink_ids->push_back(window->GetFrameSinkId());
+    return;
+  }
+  for (auto* child : window->children()) {
+    CollectFrameSinkIds(child, frame_sink_ids);
+  }
+}
+
+void CollectBrowserFrameSinkIds(const std::vector<aura::Window*>& windows,
+                                std::vector<viz::FrameSinkId>* frame_sink_ids) {
+  for (auto* window : windows) {
+    if (ash::AppType::BROWSER == static_cast<ash::AppType>(window->GetProperty(
+                                     aura::client::kAppType))) {
+      CollectFrameSinkIds(window, frame_sink_ids);
+    }
+  }
+}
+
+}  // namespace
+
+FrameThrottlingController::FrameThrottlingController(
+    ui::ContextFactory* context_factory)
+    : context_factory_(context_factory) {}
+
+FrameThrottlingController::~FrameThrottlingController() {
+  EndThrottling();
+}
+
+void FrameThrottlingController::StartThrottling(
+    const std::vector<aura::Window*>& windows,
+    uint8_t fps) {
+  std::vector<viz::FrameSinkId> frame_sink_ids;
+  frame_sink_ids.reserve(windows.size());
+
+  CollectBrowserFrameSinkIds(windows, &frame_sink_ids);
+  StartThrottling(frame_sink_ids, fps);
+}
+
+void FrameThrottlingController::StartThrottling(
+    const std::vector<viz::FrameSinkId>& frame_sink_ids,
+    uint8_t fps) {
+  DCHECK_GT(fps, 0);
+  if (context_factory_ && !frame_sink_ids.empty()) {
+    context_factory_->GetHostFrameSinkManager()->StartThrottling(
+        frame_sink_ids, base::TimeDelta::FromSeconds(1) / fps);
+  }
+}
+
+void FrameThrottlingController::EndThrottling() {
+  if (context_factory_)
+    context_factory_->GetHostFrameSinkManager()->EndThrottling();
+}
+
+}  // namespace ash
diff --git a/ash/frame_throttler/frame_throttling_controller.h b/ash/frame_throttler/frame_throttling_controller.h
new file mode 100644
index 0000000..7b32cf1
--- /dev/null
+++ b/ash/frame_throttler/frame_throttling_controller.h
@@ -0,0 +1,49 @@
+// 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_FRAME_THROTTLER_FRAME_THROTTLING_CONTROLLER_H_
+#define ASH_FRAME_THROTTLER_FRAME_THROTTLING_CONTROLLER_H_
+
+#include <stdint.h>
+#include <vector>
+#include "ash/ash_export.h"
+#include "base/macros.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+
+namespace aura {
+class Window;
+}
+
+namespace ui {
+class ContextFactory;
+}
+
+namespace ash {
+
+constexpr uint8_t kDefaultThrottleFps = 20;
+
+class ASH_EXPORT FrameThrottlingController {
+ public:
+  explicit FrameThrottlingController(ui::ContextFactory* context_factory);
+  ~FrameThrottlingController();
+
+  // Starts to throttle the framerate of |windows|.
+  void StartThrottling(const std::vector<aura::Window*>& windows,
+                       uint8_t fps = kDefaultThrottleFps);
+  // Ends throttling of all throttled windows.
+  void EndThrottling();
+
+ private:
+  void StartThrottling(const std::vector<viz::FrameSinkId>& frame_sink_ids,
+                       uint8_t fps);
+
+  ui::ContextFactory* context_factory_;
+
+  friend class FrameThrottlingControllerTest;
+  DISALLOW_COPY_AND_ASSIGN(FrameThrottlingController);
+};
+
+}  // namespace ash
+
+#endif  // ASH_FRAME_THROTTLER_FRAME_THROTTLING_CONTROLLER_H_
diff --git a/ash/public/cpp/test/app_list_test_api.h b/ash/public/cpp/test/app_list_test_api.h
new file mode 100644
index 0000000..b9e521b
--- /dev/null
+++ b/ash/public/cpp/test/app_list_test_api.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_TEST_APP_LIST_TEST_API_H_
+#define ASH_PUBLIC_CPP_TEST_APP_LIST_TEST_API_H_
+
+#include <string>
+#include <vector>
+
+#include "ash/ash_export.h"
+
+namespace ash {
+
+// Accesses ash data for app list view testing.
+class ASH_EXPORT AppListTestApi {
+ public:
+  AppListTestApi();
+  ~AppListTestApi();
+  AppListTestApi(const AppListTestApi& other) = delete;
+  AppListTestApi& operator=(const AppListTestApi& other) = delete;
+
+  // Returns ids of the items in top level app list view.
+  std::vector<std::string> GetTopLevelViewIdList();
+
+  // Creates a folder and moves all the apps in |apps| into that folder. Returns
+  // the created folder id or empty string on error. Note that |apps| should
+  // contains at least two items.
+  std::string CreateFolderWithApps(const std::vector<std::string>& apps);
+
+  // Returns the folder id that the app with |app_id| belongs to. Returns empty
+  // string if the app is not in a folder.
+  std::string GetFolderId(const std::string& app_id);
+
+  // Returns IDs of all apps that belong to the folder with |folder_id|.
+  std::vector<std::string> GetAppIdsInFolder(const std::string& folder_id);
+
+  // Moves an item to position |to_index| within the item's item list. The item
+  // can be a folder.
+  void MoveItemToPosition(const std::string& item_id, const size_t to_index);
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_TEST_APP_LIST_MODEL_API_H_
diff --git a/ash/shell.cc b/ash/shell.cc
index fcde450..349cfd83 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -53,6 +53,7 @@
 #include "ash/focus_cycler.h"
 #include "ash/frame/non_client_frame_view_ash.h"
 #include "ash/frame/snap_controller_impl.h"
+#include "ash/frame_throttler/frame_throttling_controller.h"
 #include "ash/high_contrast/high_contrast_controller.h"
 #include "ash/highlighter/highlighter_controller.h"
 #include "ash/home_screen/home_screen_controller.h"
@@ -1177,6 +1178,8 @@
   sms_observer_.reset(new SmsObserver());
   snap_controller_ = std::make_unique<SnapControllerImpl>();
   key_accessibility_enabler_ = std::make_unique<KeyAccessibilityEnabler>();
+  frame_throttling_controller_ =
+      std::make_unique<FrameThrottlingController>(context_factory);
 
   // Create UserSettingsEventLogger after |system_tray_model_| and
   // |video_detector_| which it observes.
diff --git a/ash/shell.h b/ash/shell.h
index 00d4c6c..94b9a44 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -114,6 +114,7 @@
 class EventRewriterControllerImpl;
 class EventTransformationHandler;
 class FocusCycler;
+class FrameThrottlingController;
 class HighContrastController;
 class HighlighterController;
 class HomeScreenController;
@@ -531,6 +532,10 @@
 
   PrefService* local_state() { return local_state_; }
 
+  FrameThrottlingController* frame_throttling_controller() {
+    return frame_throttling_controller_.get();
+  }
+
   // Force the shelf to query for it's current visibility state.
   // TODO(jamescook): Move to Shelf.
   void UpdateShelfVisibility();
@@ -811,6 +816,8 @@
   // volume keys.
   std::unique_ptr<KeyAccessibilityEnabler> key_accessibility_enabler_;
 
+  std::unique_ptr<FrameThrottlingController> frame_throttling_controller_;
+
   // For testing only: simulate that a modal window is open
   bool simulate_modal_window_open_for_test_ = false;
 
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index cc6e972..9048d60 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "ash/frame_throttler/frame_throttling_controller.h"
 #include "ash/keyboard/ui/keyboard_ui_controller.h"
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/window_properties.h"
@@ -369,10 +370,12 @@
       observer.OnOverviewModeEnded();
     if (!should_end_immediately && delayed_animations_.empty())
       OnEndingAnimationComplete(/*canceled=*/false);
+    Shell::Get()->frame_throttling_controller()->EndThrottling();
   } else {
     DCHECK(CanEnterOverview());
     TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ui", "OverviewController::EnterOverview",
                                       this);
+    Shell::Get()->frame_throttling_controller()->StartThrottling(windows);
 
     // Clear any animations that may be running from last overview end.
     for (const auto& animation : delayed_animations_)
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index a663086..4d87b5f 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -398,8 +398,6 @@
     SetItemBounds(inset_bounds, new_animation_type, is_first_update);
     UpdateHeaderLayout(is_first_update ? OVERVIEW_ANIMATION_NONE
                                        : new_animation_type);
-    if (is_first_update && !should_animate_when_entering_)
-      transform_window_.ClipHeaderIfNeeded(/*animate=*/false);
   }
 
   // Shadow is normally set after an animation is finished. In the case of no
@@ -767,7 +765,7 @@
     overview_item_view_->UpdatePreviewRoundedCorners(
         should_show_rounded_corners);
   } else {
-    transform_window_.UpdateRoundedCornersAndClip(should_show_rounded_corners);
+    transform_window_.UpdateRoundedCorners(should_show_rounded_corners);
   }
 
   // In addition, the shadow should be hidden if
@@ -1239,24 +1237,26 @@
     return;
   }
 
-  {
-    ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings;
-    transform_window_.BeginScopedAnimation(animation_type, &animation_settings);
-    if (animation_type ==
-            OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW &&
-        !animation_settings.empty()) {
-      animation_settings.front()->AddObserver(new AnimationObserver{
-          base::BindOnce(&OverviewItem::OnItemBoundsAnimationStarted,
-                         weak_ptr_factory_.GetWeakPtr()),
-          base::BindOnce(&OverviewItem::OnItemBoundsAnimationEnded,
-                         weak_ptr_factory_.GetWeakPtr())});
-    }
-    SetTransform(window, transform);
+  ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings;
+  transform_window_.BeginScopedAnimation(animation_type, &animation_settings);
+  if (animation_type == OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW &&
+      !animation_settings.empty()) {
+    animation_settings.front()->AddObserver(new AnimationObserver{
+        base::BindOnce(&OverviewItem::OnItemBoundsAnimationStarted,
+                       weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&OverviewItem::OnItemBoundsAnimationEnded,
+                       weak_ptr_factory_.GetWeakPtr())});
   }
+  SetTransform(window, transform);
 
-  transform_window_.SetClipping(unclipped_size_
-                                    ? GetWindowTargetBoundsWithInsets().size()
-                                    : gfx::SizeF());
+  using ClippingType = ScopedOverviewTransformWindow::ClippingType;
+  ScopedOverviewTransformWindow::ClippingData clipping_data{
+      ClippingType::kCustom, gfx::SizeF()};
+  if (unclipped_size_)
+    clipping_data.second = GetWindowTargetBoundsWithInsets().size();
+  else if (is_first_update)
+    clipping_data.first = ClippingType::kEnter;
+  transform_window_.SetClipping(clipping_data);
 }
 
 void OverviewItem::CreateItemWidget() {
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index bdc29409..1404425 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -4347,11 +4347,9 @@
             /*window_for_minimum_size=*/nullptr);
 
     ToggleOverview();
-    // Clipping like rounded corners and shadows gets updated via a delayed post
-    // task.
-    base::RunLoop().RunUntilIdle();
 
-    // Tests that in regular overview, the clipping is unchanged.
+    // Tests that after entering overview, windows with no top inset and
+    // minimized windows still have no clip.
     ASSERT_TRUE(overview_controller()->InOverviewSession());
     EXPECT_EQ(clipping1, window1->layer()->clip_rect());
     EXPECT_EQ(clipping2, window2->layer()->clip_rect());
@@ -4484,7 +4482,7 @@
                                    /*is_touch_dragging=*/false);
   overview_session()->Drag(item1, gfx::PointF());
   EXPECT_EQ(clipping1, window1->layer()->clip_rect());
-  EXPECT_EQ(clipping2, window1->layer()->clip_rect());
+  EXPECT_EQ(clipping2, window2->layer()->clip_rect());
 }
 
 // Tests that if there is only one window in the MRU window list in the overview
diff --git a/ash/wm/overview/overview_types.h b/ash/wm/overview/overview_types.h
index 3e6e8421..a55b9b2 100644
--- a/ash/wm/overview/overview_types.h
+++ b/ash/wm/overview/overview_types.h
@@ -42,9 +42,6 @@
   // Used to fade in the label which tells users they are in overview mode with
   // no window in and out.
   OVERVIEW_ANIMATION_NO_RECENTS_FADE,
-  // Used to animate the overview highlight which is activated by using tab or
-  // the arrow keys.
-  OVERVIEW_ANIMATION_FRAME_HEADER_CLIP,
   // Used to fade in all windows when window drag starts or during window drag.
   OVERVIEW_ANIMATION_OPACITY_ON_WINDOW_DRAG,
 };
diff --git a/ash/wm/overview/scoped_overview_animation_settings.cc b/ash/wm/overview/scoped_overview_animation_settings.cc
index 5426b90..863c7d0e 100644
--- a/ash/wm/overview/scoped_overview_animation_settings.cc
+++ b/ash/wm/overview/scoped_overview_animation_settings.cc
@@ -42,11 +42,6 @@
 constexpr base::TimeDelta kHomeLauncherSlideTransition =
     base::TimeDelta::FromMilliseconds(250);
 
-// Time it takes for the overview highlight to move to the next target. The same
-// time is used for fading the no recent items label.
-constexpr base::TimeDelta kOverviewHighlightTransition =
-    base::TimeDelta::FromMilliseconds(250);
-
 // Time duration of the show animation of the drop target.
 constexpr base::TimeDelta kDropTargetFade =
     base::TimeDelta::FromMilliseconds(250);
@@ -83,8 +78,7 @@
     case OVERVIEW_ANIMATION_DROP_TARGET_FADE:
       return kDropTargetFade;
     case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
-    case OVERVIEW_ANIMATION_FRAME_HEADER_CLIP:
-      return kOverviewHighlightTransition;
+      return kTransition;
     case OVERVIEW_ANIMATION_OPACITY_ON_WINDOW_DRAG:
       return kFadeInOnWindowDrag;
   }
@@ -167,7 +161,6 @@
       }
       break;
     case OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER:
-    case OVERVIEW_ANIMATION_FRAME_HEADER_CLIP:
       animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
       animation_settings_->SetPreemptionStrategy(
           ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
diff --git a/ash/wm/overview/scoped_overview_transform_window.cc b/ash/wm/overview/scoped_overview_transform_window.cc
index 122df248..d4168cf7 100644
--- a/ash/wm/overview/scoped_overview_transform_window.cc
+++ b/ash/wm/overview/scoped_overview_transform_window.cc
@@ -32,7 +32,13 @@
 #include "ui/aura/scoped_window_event_targeting_blocker.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/layer_animator.h"
 #include "ui/compositor/layer_observer.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/gfx/transform_util.h"
 #include "ui/views/layout/layout_provider.h"
 #include "ui/views/widget/widget.h"
@@ -51,6 +57,72 @@
 // Delay closing window to allow it to shrink and fade out.
 constexpr int kCloseWindowDelayInMilliseconds = 150;
 
+// Layer animation observer that is attached to a clip animation. Removes the
+// clip and then self destructs after the animation is finished.
+class RemoveClipObserver : public ui::ImplicitAnimationObserver,
+                           public aura::WindowObserver {
+ public:
+  explicit RemoveClipObserver(aura::Window* window) : window_(window) {
+    auto* animator = window_->layer()->GetAnimator();
+    DCHECK(window_->layer()->GetAnimator()->is_animating());
+
+    const auto original_transition_duration = animator->GetTransitionDuration();
+    // Don't let |settings| overwrite the existing animation's duration.
+    ui::ScopedLayerAnimationSettings settings{animator};
+    settings.SetTransitionDuration(original_transition_duration);
+    settings.AddObserver(this);
+    window_->AddObserver(this);
+  }
+  RemoveClipObserver(const RemoveClipObserver&) = delete;
+  RemoveClipObserver& operator=(const RemoveClipObserver&) = delete;
+  ~RemoveClipObserver() override {
+    StopObservingImplicitAnimations();
+    window_->RemoveObserver(this);
+    window_ = nullptr;
+  }
+
+ private:
+  // ui::ImplicitAnimationObserver:
+  void OnImplicitAnimationsCompleted() override {
+    window_->layer()->SetClipRect(gfx::Rect());
+    delete this;
+  }
+
+  // aura::WindowObserver:
+  void OnWindowDestroying(aura::Window* window) override {
+    DCHECK_EQ(window_, window);
+    delete this;
+  }
+
+  // Guaranteed to be not null for the duration of |this|.
+  aura::Window* window_;
+};
+
+// Clips |window| to |clip_rect|. If |clip_rect| is empty and there is an
+// animation, animate first to a clip the size of |window|, then remove the
+// clip. Otherwise the clip animation will clip away all the contents while it
+// animates towards an empty clip rect (but not yet empty) before reshowing it
+// once the clip rect is really empty. An empty clip rect means a request to
+// clip nothing.
+void ClipWindow(aura::Window* window, const gfx::Rect& clip_rect) {
+  DCHECK(window);
+
+  ui::LayerAnimator* animator = window->layer()->GetAnimator();
+  const gfx::Rect target_clip_rect = animator->GetTargetClipRect();
+  if (target_clip_rect == clip_rect)
+    return;
+
+  gfx::Rect new_clip_rect = clip_rect;
+  if (new_clip_rect.IsEmpty() && animator->is_animating()) {
+    // Animate to a clip the size of |window|. Create a self deleting object
+    // which removes the clip when the animation is finished.
+    new_clip_rect = gfx::Rect(window->bounds().size());
+    new RemoveClipObserver(window);
+  }
+
+  window->layer()->SetClipRect(new_clip_rect);
+}
+
 }  // namespace
 
 class ScopedOverviewTransformWindow::LayerCachingAndFilteringObserver
@@ -150,9 +222,8 @@
     transient->RemoveObserver(this);
   }
 
-  // Remove rounded corners and clipping.
-  UpdateRoundedCornersAndClip(/*show=*/false);
-  window_->layer()->SetClipRect(original_clip_rect_);
+  if (!IsMinimized())
+    UpdateRoundedCorners(/*show=*/false);
   aura::client::GetTransientWindowClient()->RemoveObserver(this);
 }
 
@@ -219,6 +290,7 @@
   ScopedOverviewAnimationSettings animation_settings(
       overview_item_->GetExitOverviewAnimationType(), window_);
   SetOpacity(original_opacity_);
+  SetClipping({ClippingType::kExit, gfx::SizeF()});
 }
 
 void ScopedOverviewTransformWindow::BeginScopedAnimation(
@@ -286,23 +358,42 @@
     window->layer()->SetOpacity(opacity);
 }
 
-void ScopedOverviewTransformWindow::SetClipping(const gfx::SizeF& size) {
-  has_aspect_ratio_clipping_ = !size.IsEmpty();
-
-  // If width or height are 0, restore the overview clipping.
-  if (size.IsEmpty()) {
-    window_->layer()->SetClipRect(overview_clip_rect_);
-    return;
+void ScopedOverviewTransformWindow::SetClipping(
+    const ClippingData& clipping_data) {
+  gfx::SizeF size;
+  switch (clipping_data.first) {
+    case ClippingType::kEnter:
+      size = gfx::SizeF(window_->bounds().size());
+      break;
+    case ClippingType::kExit:
+      ClipWindow(window_, original_clip_rect_);
+      return;
+    case ClippingType::kCustom:
+      size = clipping_data.second;
+      if (size.IsEmpty()) {
+        // Given size is empty so we fallback to the overview clipping, which is
+        // the size of the window. The header will be accounted for below.
+        size = gfx::SizeF(window_->bounds().size());
+      } else {
+        // Transform affects the clip rect, so take that into account.
+        const gfx::Vector2dF scale =
+            window_->layer()->GetTargetTransform().Scale2d();
+        size.Scale(1 / scale.x(), 1 / scale.y());
+      }
+      break;
   }
 
-  // Compute the clip rect. Transform affects the clip rect, so take that into
-  // account.
-  gfx::Rect clip_rect;
-  const gfx::Vector2dF scale = window_->layer()->GetTargetTransform().Scale2d();
-  clip_rect.set_y(GetTopInset());
-  clip_rect.set_width(size.width() / scale.x());
-  clip_rect.set_height(size.height() / scale.y());
-  window_->layer()->SetClipRect(clip_rect);
+  if (size.IsEmpty())
+    return;
+
+  gfx::Rect clip_rect(gfx::ToRoundedSize(size));
+  // We add 1 to the top_inset, because in some cases, the header is not
+  // clipped fully due to what seems to be a rounding error.
+  // TODO(afakhry|sammiequon): Investigate a proper fix for this.
+  const int top_inset = GetTopInset();
+  if (top_inset > 0)
+    clip_rect.Inset(gfx::Insets(top_inset + 1, 0, 0, 0));
+  ClipWindow(window_, clip_rect);
 }
 
 gfx::RectF ScopedOverviewTransformWindow::ShrinkRectToFitPreservingAspectRatio(
@@ -397,52 +488,18 @@
   type_ = GetWindowDimensionsType(window_->bounds().size());
 }
 
-void ScopedOverviewTransformWindow::UpdateRoundedCornersAndClip(bool show) {
+void ScopedOverviewTransformWindow::UpdateRoundedCorners(bool show) {
   // Hide the corners if minimized, OverviewItemView will handle showing the
   // rounded corners on the UI.
-  const bool show_corners = show && !IsMinimized();
-  // Add the clipping which gives the overview item rounded corners, and add the
-  // shadow around the window.
+  DCHECK(!IsMinimized());
+
   ui::Layer* layer = window_->layer();
   const float scale = layer->transform().Scale2d().x();
   const int radius =
       views::LayoutProvider::Get()->GetCornerRadiusMetric(views::EMPHASIS_LOW);
-  const gfx::RoundedCornersF radii(show_corners ? (radius / scale) : 0.0f);
+  const gfx::RoundedCornersF radii(show ? (radius / scale) : 0.0f);
   layer->SetRoundedCornerRadius(radii);
   layer->SetIsFastRoundedCorner(true);
-
-  if (!show || layer->GetAnimator()->is_animating() || IsMinimized())
-    return;
-
-  ClipHeaderIfNeeded(true);
-}
-
-void ScopedOverviewTransformWindow::ClipHeaderIfNeeded(bool animate) {
-  const int top_inset = GetTopInset();
-  if (top_inset <= 0)
-    return;
-
-  // Clipping a window to preserve aspect ratios will account for the header, so
-  // no need to clip here.
-  if (has_aspect_ratio_clipping_)
-    return;
-
-  gfx::Rect clip_rect(window_->bounds().size());
-  // We add 1 to the top_inset, because in some cases, the header is not
-  // clipped fully due to what seems to be a rounding error.
-  // TODO(afakhry|sammiequon): Investigate a proper fix for this.
-  clip_rect.Inset(0, top_inset + 1, 0, 0);
-
-  if (overview_clip_rect_ == clip_rect)
-    return;
-
-  std::unique_ptr<ScopedOverviewAnimationSettings> settings;
-  if (animate) {
-    settings = std::make_unique<ScopedOverviewAnimationSettings>(
-        OVERVIEW_ANIMATION_FRAME_HEADER_CLIP, window_);
-  }
-  window_->layer()->SetClipRect(clip_rect);
-  overview_clip_rect_ = clip_rect;
 }
 
 void ScopedOverviewTransformWindow::OnTransientChildWindowAdded(
diff --git a/ash/wm/overview/scoped_overview_transform_window.h b/ash/wm/overview/scoped_overview_transform_window.h
index 7033671..e59a135 100644
--- a/ash/wm/overview/scoped_overview_transform_window.h
+++ b/ash/wm/overview/scoped_overview_transform_window.h
@@ -12,7 +12,6 @@
 #include "ash/wm/overview/overview_session.h"
 #include "ash/wm/overview/overview_types.h"
 #include "base/gtest_prod_util.h"
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "ui/aura/client/transient_window_client_observer.h"
@@ -43,6 +42,14 @@
   using ScopedAnimationSettings =
       std::vector<std::unique_ptr<ScopedOverviewAnimationSettings>>;
 
+  // Information needed to do a clip on |window_|.
+  enum class ClippingType {
+    kEnter,   // Clips away the header if it exists.
+    kExit,    // Removes or resets clip.
+    kCustom,  // Clips to custom given bounds.
+  };
+  using ClippingData = std::pair<ClippingType, gfx::SizeF>;
+
   // Calculates and returns an optimal scale ratio. This is only taking into
   // account |size.height()| as the width can vary.
   static float GetItemScale(const gfx::SizeF& source,
@@ -55,6 +62,9 @@
 
   ScopedOverviewTransformWindow(OverviewItem* overview_item,
                                 aura::Window* window);
+  ScopedOverviewTransformWindow(const ScopedOverviewTransformWindow&) = delete;
+  ScopedOverviewTransformWindow& operator=(
+      const ScopedOverviewTransformWindow&) = delete;
   ~ScopedOverviewTransformWindow() override;
 
   // Starts an animation sequence which will use animation settings specified by
@@ -97,9 +107,8 @@
   // Sets the opacity of the managed windows.
   void SetOpacity(float opacity);
 
-  // Apply clipping on the managed windows. If |size| is empty, then restore
-  // |overview_clip_rect_|.
-  void SetClipping(const gfx::SizeF& size);
+  // Apply clipping on the managed windows.
+  void SetClipping(const ClippingData& clipping_data);
 
   // Returns |rect| having been shrunk to fit within |bounds| (preserving the
   // aspect ratio). Takes into account a window header that is |top_view_inset|
@@ -126,14 +135,8 @@
   // change. Must be called before PositionWindows in OverviewGrid.
   void UpdateWindowDimensionsType();
 
-  // Updates the rounded corners and clipping on the window. Note that the
-  // rounded corners can be hidden with |show| set to false, but the clipping
-  // stays for the duration of overview once applied.
-  void UpdateRoundedCornersAndClip(bool show);
-
-  // Clip the top portion of the window that normally contains the caption (if
-  // any).
-  void ClipHeaderIfNeeded(bool animate);
+  // Updates the rounded corners on |window_|.
+  void UpdateRoundedCorners(bool show);
 
   // aura::client::TransientWindowClientObserver:
   void OnTransientChildWindowAdded(aura::Window* parent,
@@ -198,20 +201,9 @@
   // mode.
   gfx::Rect original_clip_rect_;
 
-  // The clippng on the layer of |window_| after entering overview mode.
-  // Additional clipping may be added, and when that additional clipping is
-  // removed, we should go back to this clipping.
-  gfx::Rect overview_clip_rect_;
-
-  // True if a window is clipped to match splitview bounds. If true, the
-  // splitview clipping overrides any top view inset clipping there may be.
-  bool has_aspect_ratio_clipping_ = false;
-
   std::unique_ptr<ScopedOverviewHideWindows> hidden_transient_children_;
 
   base::WeakPtrFactory<ScopedOverviewTransformWindow> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedOverviewTransformWindow);
 };
 
 }  // namespace ash
diff --git a/base/task/thread_pool/job_task_source.cc b/base/task/thread_pool/job_task_source.cc
index 1e6b04c..d984e86c 100644
--- a/base/task/thread_pool/job_task_source.cc
+++ b/base/task/thread_pool/job_task_source.cc
@@ -18,6 +18,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "base/time/time_override.h"
+#include "base/trace_event/base_tracing.h"
 
 namespace base {
 namespace internal {
@@ -34,48 +35,6 @@
 
 }  // namespace
 
-// Memory ordering on |state_| operations
-//
-// The write operation on |state_| in WillRunTask() uses
-// std::memory_order_release, matched by std::memory_order_acquire on read
-// operations (in DidProcessTask()) to establish a
-// Release-Acquire ordering. When a call to WillRunTask() is caused by an
-// increase of max concurrency followed by an associated
-// NotifyConcurrencyIncrease(), the priority queue lock guarantees an
-// happens-after relation with NotifyConcurrencyIncrease(). This ensures that an
-// increase of max concurrency that happened-before NotifyConcurrencyIncrease()
-// is visible to a read operation that happens-after WillRunTask().
-//
-// In DidProcessTask(), this is necessary to
-// ensure that the task source is always re-enqueued when it needs to. When the
-// task source needs to be queued, either because the current task yielded or
-// because of NotifyConcurrencyIncrease(), one of the following is true:
-//   A) DidProcessTask() happens-after WillRunTask():
-//    T1: Current task returns (because it is done) or yields.
-//    T2: Increases the value returned by GetMaxConcurrency()
-//        NotifyConcurrencyIncrease() enqueues the task source
-//    T3: WillRunTask(), in response to the concurrency increase - Release
-//        Does not keep the TaskSource in PriorityQueue because it is at max
-//        concurrency
-//    T1: DidProcessTask() - Acquire - Because of memory barrier, sees the same
-//        (or newer) max concurrency as T2
-//        Re-enqueues the TaskSource because no longer at max concurrency
-//      Without the memory barrier, T1 may see an outdated max concurrency that
-//      is lower than the actual max concurrency and won't re-enqueue the
-//      task source, because it thinks it's already saturated.
-//      The task source often needs to be re-enqueued if its task
-//      completed because it yielded and |max_concurrency| wasn't decreased.
-//   B) DidProcessTask() happens-before WillRunTask():
-//    T1: Current task returns (because it is done) or yields
-//    T2: Increases the value returned by GetMaxConcurrency()
-//        NotifyConcurrencyIncrease() enqueues the task source
-//    T1: DidProcessTask() - Acquire (ineffective)
-//      Since the task source is already in the queue, it doesn't matter
-//      whether T1 re-enqueues the task source or not.
-// Note that stale values the other way around can cause incorrectly
-// re-enqueuing this task_source, which is not an issue because the queues
-// support empty task sources.
-
 JobTaskSource::State::State() = default;
 JobTaskSource::State::~State() = default;
 
@@ -83,46 +42,19 @@
   return {value_.fetch_or(kCanceledMask, std::memory_order_relaxed)};
 }
 
-JobTaskSource::State::Value
-JobTaskSource::State::TryIncrementWorkerCountFromWorkerRelease(
-    size_t max_concurrency) {
-  uint32_t value_before_add = value_.load(std::memory_order_relaxed);
-
-  // std::memory_order_release on success to establish Release-Acquire ordering
-  // with DecrementWorkerCountAcquire()  (see Memory Ordering comment at top of
-  // the file).
-  while (!(value_before_add & kCanceledMask) &&
-         (value_before_add >> kWorkerCountBitOffset) < max_concurrency &&
-         !value_.compare_exchange_weak(
-             value_before_add, value_before_add + kWorkerCountIncrement,
-             std::memory_order_release, std::memory_order_relaxed)) {
-  }
-  return {value_before_add};
-}
-
-JobTaskSource::State::Value
-JobTaskSource::State::DecrementWorkerCountFromWorkerAcquire() {
-  const size_t value_before_sub =
-      value_.fetch_sub(kWorkerCountIncrement, std::memory_order_acquire);
-  DCHECK((value_before_sub >> kWorkerCountBitOffset) > 0);
-  return {value_before_sub};
-}
-
-JobTaskSource::State::Value
-JobTaskSource::State::IncrementWorkerCountFromJoiningThread() {
-  size_t value_before_add =
-      value_.fetch_add(kWorkerCountIncrement, std::memory_order_relaxed);
-  return {value_before_add};
-}
-
-JobTaskSource::State::Value
-JobTaskSource::State::DecrementWorkerCountFromJoiningThread() {
+JobTaskSource::State::Value JobTaskSource::State::DecrementWorkerCount() {
   const size_t value_before_sub =
       value_.fetch_sub(kWorkerCountIncrement, std::memory_order_relaxed);
   DCHECK((value_before_sub >> kWorkerCountBitOffset) > 0);
   return {value_before_sub};
 }
 
+JobTaskSource::State::Value JobTaskSource::State::IncrementWorkerCount() {
+  size_t value_before_add =
+      value_.fetch_add(kWorkerCountIncrement, std::memory_order_relaxed);
+  return {value_before_add};
+}
+
 JobTaskSource::State::Value JobTaskSource::State::Load() const {
   return {value_.load(std::memory_order_relaxed)};
 }
@@ -167,6 +99,12 @@
       queue_time_(TimeTicks::Now()),
       delegate_(delegate) {
   DCHECK(delegate_);
+#if DCHECK_IS_ON()
+  version_condition_for_dcheck_ = worker_lock_.CreateConditionVariable();
+  // Prevent wait from triggering a ScopedBlockingCall as this would add
+  // complexity outside this DCHECK-only code.
+  version_condition_for_dcheck_->declare_only_used_while_idle();
+#endif  // DCHECK_IS_ON()
 }
 
 JobTaskSource::~JobTaskSource() {
@@ -179,15 +117,13 @@
 }
 
 bool JobTaskSource::WillJoin() {
-  {
-    CheckedAutoLock auto_lock(lock_);
-    DCHECK(!worker_released_condition_);  // This may only be called once.
-    worker_released_condition_ = lock_.CreateConditionVariable();
-  }
-  // std::memory_order_relaxed on |worker_count_| is sufficient because call to
-  // GetMaxConcurrency() is used for a best effort early exit. Stale values will
-  // only cause WaitForParticipationOpportunity() to be called.
-  const auto state_before_add = state_.IncrementWorkerCountFromJoiningThread();
+  CheckedAutoLock auto_lock(worker_lock_);
+  DCHECK(!worker_released_condition_);  // This may only be called once.
+  worker_released_condition_ = worker_lock_.CreateConditionVariable();
+  // Prevent wait from triggering a ScopedBlockingCall as this would cause
+  // |ThreadGroup::lock_| to be acquired, causing lock inversion.
+  worker_released_condition_->declare_only_used_while_idle();
+  const auto state_before_add = state_.IncrementWorkerCount();
 
   if (!state_before_add.is_canceled() &&
       state_before_add.worker_count() < GetMaxConcurrency()) {
@@ -200,33 +136,33 @@
   JobDelegate job_delegate{this, nullptr};
   worker_task_.Run(&job_delegate);
 
-  // std::memory_order_relaxed on |worker_count_| is sufficient because the call
-  // to GetMaxConcurrency() is used for a best effort early exit. Stale values
-  // will only cause WaitForParticipationOpportunity() to be called.
-  const auto state = state_.Load();
+  // It is safe to read |state_| without a lock since this variable is atomic
+  // and the call to GetMaxConcurrency() is used for a best effort early exit.
+  // Stale values will only cause WaitForParticipationOpportunity() to be
+  // called.
+  const auto state = TS_UNCHECKED_READ(state_).Load();
   if (!state.is_canceled() && state.worker_count() <= GetMaxConcurrency())
     return true;
 
+  CheckedAutoLock auto_lock(worker_lock_);
   return WaitForParticipationOpportunity();
 }
 
 void JobTaskSource::Cancel(TaskSource::Transaction* transaction) {
+  CheckedAutoLock auto_lock(worker_lock_);
   // Sets the kCanceledMask bit on |state_| so that further calls to
   // WillRunTask() never succeed. std::memory_order_relaxed is sufficient
   // because this task source never needs to be re-enqueued after Cancel().
   state_.Cancel();
 
 #if DCHECK_IS_ON()
-  {
-    AutoLock auto_lock(version_lock_);
     ++increase_version_;
-    version_condition_.Broadcast();
-  }
+    version_condition_for_dcheck_->Broadcast();
 #endif  // DCHECK_IS_ON()
 }
 
+// EXCLUSIVE_LOCK_REQUIRED(worker_lock_)
 bool JobTaskSource::WaitForParticipationOpportunity() {
-  CheckedAutoLock auto_lock(lock_);
   DCHECK(!join_flag_.IsWaiting());
 
   // std::memory_order_relaxed is sufficient because no other state is
@@ -248,6 +184,7 @@
     // |lock_| is taken and |worker_released_condition_| signaled if necessary:
     // 1- In DidProcessTask(), after worker count is decremented.
     // 2- In NotifyConcurrencyIncrease(), following a max_concurrency increase.
+    TRACE_EVENT0("base", "Job.WaitForParticipationOpportunity");
     worker_released_condition_->Wait();
     state = state_.Load();
     max_concurrency = GetMaxConcurrency();
@@ -259,16 +196,19 @@
   // Only the joining thread remains.
   DCHECK_EQ(state.worker_count(), 1U);
   DCHECK(state.is_canceled() || max_concurrency == 0U);
-  state_.DecrementWorkerCountFromJoiningThread();
+  state_.DecrementWorkerCount();
   return false;
 }
 
 TaskSource::RunStatus JobTaskSource::WillRunTask() {
+  CheckedAutoLock auto_lock(worker_lock_);
+
   const size_t max_concurrency = GetMaxConcurrency();
-  // std::memory_order_release on success to establish Release-Acquire ordering
-  // with read operations (see Memory Ordering comment at top of the file).
-  const auto state_before_add =
-      state_.TryIncrementWorkerCountFromWorkerRelease(max_concurrency);
+  auto state_before_add = state_.Load();
+  if (!state_before_add.is_canceled() &&
+      state_before_add.worker_count() < max_concurrency) {
+    state_before_add = state_.IncrementWorkerCount();
+  }
 
   // Don't allow this worker to run the task if either:
   //   A) |state_| was canceled.
@@ -289,9 +229,9 @@
 }
 
 size_t JobTaskSource::GetRemainingConcurrency() const {
-  // std::memory_order_relaxed is sufficient because no other state is
-  // synchronized with GetRemainingConcurrency().
-  const auto state = state_.Load();
+  // It is safe to read |state_| without a lock since this variable is atomic,
+  // and no other state is synchronized with GetRemainingConcurrency().
+  const auto state = TS_UNCHECKED_READ(state_).Load();
   const size_t max_concurrency = GetMaxConcurrency();
   // Avoid underflows.
   if (state.is_canceled() || state.worker_count() > max_concurrency)
@@ -302,9 +242,9 @@
 void JobTaskSource::NotifyConcurrencyIncrease() {
 #if DCHECK_IS_ON()
   {
-    AutoLock auto_lock(version_lock_);
+    CheckedAutoLock auto_lock(worker_lock_);
     ++increase_version_;
-    version_condition_.Broadcast();
+    version_condition_for_dcheck_->Broadcast();
   }
 #endif  // DCHECK_IS_ON()
 
@@ -316,7 +256,7 @@
   {
     // Lock is taken to access |join_flag_| below and signal
     // |worker_released_condition_|.
-    CheckedAutoLock auto_lock(lock_);
+    CheckedAutoLock auto_lock(worker_lock_);
     if (join_flag_.ShouldWorkerSignal())
       worker_released_condition_->Signal();
   }
@@ -358,22 +298,22 @@
 }
 
 bool JobTaskSource::ShouldYield() {
-  // It is safe to read |join_flag_| without a lock since this
-  // variable is atomic, keeping in mind that threads may not immediately see
+  // It is safe to read |join_flag_| and |state_| without a lock since these
+  // variables are atomic, keeping in mind that threads may not immediately see
   // the new value when it is updated.
   return TS_UNCHECKED_READ(join_flag_).ShouldWorkerYield() ||
-         state_.Load().is_canceled();
+         TS_UNCHECKED_READ(state_).Load().is_canceled();
 }
 
 #if DCHECK_IS_ON()
 
 size_t JobTaskSource::GetConcurrencyIncreaseVersion() const {
-  AutoLock auto_lock(version_lock_);
+  CheckedAutoLock auto_lock(worker_lock_);
   return increase_version_;
 }
 
 bool JobTaskSource::WaitForConcurrencyIncreaseUpdate(size_t recorded_version) {
-  AutoLock auto_lock(version_lock_);
+  CheckedAutoLock auto_lock(worker_lock_);
   constexpr TimeDelta timeout = TimeDelta::FromSeconds(1);
   const base::TimeTicks start_time = subtle::TimeTicksNowIgnoringOverride();
   do {
@@ -384,7 +324,7 @@
     // Waiting is acceptable because it is in DCHECK-only code.
     ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
         allow_base_sync_primitives;
-    version_condition_.TimedWait(timeout);
+    version_condition_for_dcheck_->TimedWait(timeout);
   } while (subtle::TimeTicksNowIgnoringOverride() - start_time < timeout);
   return false;
 }
@@ -394,21 +334,16 @@
 Task JobTaskSource::TakeTask(TaskSource::Transaction* transaction) {
   // JobTaskSource members are not lock-protected so no need to acquire a lock
   // if |transaction| is nullptr.
-  DCHECK_GT(state_.Load().worker_count(), 0U);
+  DCHECK_GT(TS_UNCHECKED_READ(state_).Load().worker_count(), 0U);
   DCHECK(primary_task_);
   return Task(from_here_, primary_task_, TimeDelta());
 }
 
-bool JobTaskSource::DidProcessTask(TaskSource::Transaction* transaction) {
+bool JobTaskSource::DidProcessTask(TaskSource::Transaction* /*transaction*/) {
   // Lock is needed to access |join_flag_| below and signal
-  // |worker_released_condition_|. If |transaction|, then |lock_| is already
-  // taken.
-  CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_);
-  AnnotateAcquiredLockAlias annotate(lock_, lock_);
-
-  // std::memory_order_acquire to establish Release-Acquire ordering with
-  // WillRunTask() (see Memory Ordering comment at top of the file).
-  const auto state_before_sub = state_.DecrementWorkerCountFromWorkerAcquire();
+  // |worker_released_condition_|.
+  CheckedAutoLock auto_lock(worker_lock_);
+  const auto state_before_sub = state_.DecrementWorkerCount();
 
   if (join_flag_.ShouldWorkerSignal())
     worker_released_condition_->Signal();
diff --git a/base/task/thread_pool/job_task_source.h b/base/task/thread_pool/job_task_source.h
index 7b8c13e4..43b6a7ed 100644
--- a/base/task/thread_pool/job_task_source.h
+++ b/base/task/thread_pool/job_task_source.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
+#include "base/task/common/checked_lock.h"
 #include "base/task/post_job.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool/sequence_sort_key.h"
@@ -91,7 +91,9 @@
 
  private:
   // Atomic internal state to track the number of workers running a task from
-  // this JobTaskSource and whether this JobTaskSource is canceled.
+  // this JobTaskSource and whether this JobTaskSource is canceled. All
+  // operations are performed with std::memory_order_relaxed as State is only
+  // ever modified under a lock or read atomically (optimistic read).
   class State {
    public:
     static constexpr size_t kCanceledMask = 1;
@@ -109,28 +111,17 @@
     State();
     ~State();
 
-    // Sets as canceled using std::memory_order_relaxed. Returns the state
+    // Sets as canceled. Returns the state
     // before the operation.
     Value Cancel();
 
-    // Increments the worker count by 1 if smaller than |max_concurrency| and if
-    // |!is_canceled()|, using std::memory_order_release, and returns the state
-    // before the operation. Equivalent to Load() otherwise.
-    Value TryIncrementWorkerCountFromWorkerRelease(size_t max_concurrency);
+    // Increments the worker count by 1. Returns the state before the operation.
+    Value IncrementWorkerCount();
 
-    // Decrements the worker count by 1 using std::memory_order_acquire. Returns
-    // the state before the operation.
-    Value DecrementWorkerCountFromWorkerAcquire();
+    // Decrements the worker count by 1. Returns the state before the operation.
+    Value DecrementWorkerCount();
 
-    // Increments the worker count by 1 using std::memory_order_relaxed. Returns
-    // the state before the operation.
-    Value IncrementWorkerCountFromJoiningThread();
-
-    // Decrements the worker count by 1 using std::memory_order_relaxed. Returns
-    // the state before the operation.
-    Value DecrementWorkerCountFromJoiningThread();
-
-    // Loads and returns the state, using std::memory_order_relaxed.
+    // Loads and returns the state.
     Value Load() const;
 
    private:
@@ -186,7 +177,7 @@
   // DidProcessTask()). Returns true if the joining thread should run a task, or
   // false if joining was completed and all other workers returned because
   // either there's no work remaining or Job was cancelled.
-  bool WaitForParticipationOpportunity();
+  bool WaitForParticipationOpportunity() EXCLUSIVE_LOCKS_REQUIRED(worker_lock_);
 
   // TaskSource:
   RunStatus WillRunTask() override;
@@ -195,15 +186,20 @@
   bool DidProcessTask(TaskSource::Transaction* transaction) override;
   SequenceSortKey GetSortKey() const override;
 
-  // Current atomic state.
-  State state_;
-  std::atomic<uint32_t> assigned_task_ids_{0};
+  // Synchronizes access to workers state.
+  mutable CheckedLock worker_lock_{UniversalSuccessor()};
+
+  // Current atomic state (atomic despite the lock to allow optimistic reads
+  // without the lock).
+  State state_ GUARDED_BY(worker_lock_);
   // Normally, |join_flag_| is protected by |lock_|, except in ShouldYield()
   // hence the use of atomics.
-  JoinFlag join_flag_ GUARDED_BY(lock_);
+  JoinFlag join_flag_ GUARDED_BY(worker_lock_);
   // Signaled when |join_flag_| is kWaiting* and a worker returns.
   std::unique_ptr<ConditionVariable> worker_released_condition_
-      GUARDED_BY(lock_);
+      GUARDED_BY(worker_lock_);
+
+  std::atomic<uint32_t> assigned_task_ids_{0};
 
   const Location from_here_;
   RepeatingCallback<size_t()> max_concurrency_callback_;
@@ -217,12 +213,10 @@
   PooledTaskRunnerDelegate* delegate_;
 
 #if DCHECK_IS_ON()
-  // Synchronizes accesses to |increase_version_|.
-  mutable Lock version_lock_;
-  // Signaled whenever increase_version_ is updated.
-  ConditionVariable version_condition_{&version_lock_};
+  // Signaled whenever |increase_version_| is updated.
+  std::unique_ptr<ConditionVariable> version_condition_for_dcheck_;
   // Incremented every time max concurrency is increased.
-  size_t increase_version_ GUARDED_BY(version_lock_) = 0;
+  size_t increase_version_ GUARDED_BY(worker_lock_) = 0;
 #endif  // DCHECK_IS_ON()
 
   DISALLOW_COPY_AND_ASSIGN(JobTaskSource);
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index c39cc24..0154990 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -344,14 +344,12 @@
 config("cfi_linker") {
   # Control Flow Guard (CFG)
   # https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065.aspx
-  # /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG can’t be
+  # /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG cannot be
   # turned on either.
-  # CFG seems to lead to random corruption with incremental linking so turn off
-  # CFG in component builds. https://crbug.com/812421
   # ASan and CFG leads to slow process startup. Chromium's test runner uses
   # lots of child processes, so this means things are really slow. Disable CFG
   # for now. https://crbug.com/846966
-  if (!is_debug && !is_component_build && !is_asan) {
+  if (!is_debug && !is_asan) {
     # Turn on CFG bitmap generation and CFG load config.
     ldflags = [ "/guard:cf" ]
   }
diff --git a/build/ios/intent_definition.gni b/build/ios/intent_definition.gni
index f9e2e02..259f287 100644
--- a/build/ios/intent_definition.gni
+++ b/build/ios/intent_definition.gni
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/ios/ios_sdk.gni")
+
 # Template to compile an .intentdefinition file.
 #
 # Arguments
@@ -24,6 +26,9 @@
   assert(defined(invoker.intent_names) && invoker.intent_names != [],
          "intent_names must be defined for $target_name")
 
+  assert(xcode_version_int >= 1140,
+         "intent_definition requires Xcode 11.4 or higher")
+
   _compile_intent_target = "${target_name}_compile_intent"
   _compile_intent_output =
       "$target_gen_dir/" + get_path_info(invoker.intent_file, "file")
diff --git a/build/lacros/test_runner.py b/build/lacros/test_runner.py
index 7b013087..c275bb7 100755
--- a/build/lacros/test_runner.py
+++ b/build/lacros/test_runner.py
@@ -13,10 +13,12 @@
 
 import argparse
 import os
+import logging
 import shutil
 import subprocess
 import sys
 import tempfile
+import time
 import zipfile
 
 _SRC_ROOT = os.path.abspath(
@@ -37,8 +39,6 @@
 _GS_ASH_CHROME_PATH = 'linux-chromeos/chrome-linux-chromeos.zip'
 
 # Directory to cache downloaded ash-chrome versions to avoid re-downloading.
-# TODO(crbug.com/1104318): Cleans up unused versions regularly to avoid
-# consuming too much disk space.
 _PREBUILT_ASH_CHROME_DIR = os.path.join(os.path.dirname(__file__),
                                         'prebuilt_ash_chrome')
 
@@ -48,6 +48,39 @@
   return os.path.join(_PREBUILT_ASH_CHROME_DIR, version)
 
 
+def _remove_unused_ash_chrome_versions(version_to_skip):
+  """Removes unused ash-chrome versions to save disk space.
+
+  Currently, when an ash-chrome zip is downloaded and unpacked, the atime/mtime
+  of the dir and the files are NOW instead of the time when they were built, but
+  there is no garanteen it will always be the behavior in the future, so avoid
+  removing the current version just in case.
+
+  Args:
+    version_to_skip (str): the version to skip removing regardless of its age.
+  """
+  days = 7
+  expiration_duration = 60 * 60 * 24 * days
+
+  for f in os.listdir(_PREBUILT_ASH_CHROME_DIR):
+    if f == version_to_skip:
+      continue
+
+    p = os.path.join(_PREBUILT_ASH_CHROME_DIR, f)
+    if os.path.isfile(p):
+      # The prebuilt ash-chrome dir is NOT supposed to contain any files, remove
+      # them to keep the directory clean.
+      os.remove(p)
+      continue
+
+    age = time.time() - os.path.getatime(os.path.join(p, 'chrome'))
+    if age > expiration_duration:
+      logging.info(
+          'Removing ash-chrome: "%s" as it hasn\'t been used in the '
+          'past %d days', p, days)
+      shutil.rmtree(p)
+
+
 def _DownloadAshChromeIfNecessary(version):
   """Download a given version of ash-chrome if not already exists.
 
@@ -97,6 +130,8 @@
       for info in zf.infolist():
         ExtractFile(zf, info, ash_chrome_dir)
 
+  _remove_unused_ash_chrome_versions(version)
+
 
 def _GetLatestVersionOfAshChrome():
   """Returns the latest version of uploaded official ash-chrome."""
@@ -123,6 +158,7 @@
 
 
 def Main():
+  logging.basicConfig(level=logging.INFO)
   args, forward_args = _ParseArguments()
   return subprocess.call([args.command] + forward_args)
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index bc33593..5aafa00f 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1217,6 +1217,7 @@
     "//chrome/android/features/vr:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/tab:java",
+    "//chrome/browser/tabmodel:java",
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/util:java",
     "//chrome/test/android:chrome_java_test_support",
@@ -2253,7 +2254,7 @@
     }
     if (!is_java_debug) {
       proguard_enabled = true
-      proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ]
+      proguard_configs = [ "//chrome/android/proguard/apk_for_test.flags" ]
     }
 
     # TODO(crbug.com/993340): Update test goldens with webp versions of images.
@@ -2305,7 +2306,7 @@
         proguard_configs = []
       }
       proguard_enabled = true
-      proguard_configs += [ "//chrome/android/java/apk_for_test.flags" ]
+      proguard_configs += [ "//chrome/android/proguard/apk_for_test.flags" ]
     }
   }
 }
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 53286c0..8178b5f 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1543,7 +1543,6 @@
   "java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java",
   "java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java",
   "java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java",
-  "java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelDelegate.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 53d15db..19f597a 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -320,7 +320,7 @@
         proguard_configs = []
       }
       proguard_configs += [
-        "//chrome/android/java/proguard.flags",
+        "//chrome/android/proguard/main.flags",
         "//base/android/proguard/chromium_apk.flags",
         "//base/android/proguard/chromium_code.flags",
       ]
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index e00b852..c252615 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -243,6 +243,7 @@
   "javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java",
   "javatests/src/org/chromium/chrome/browser/jsdialog/JavascriptAppModalDialogTest.java",
   "javatests/src/org/chromium/chrome/browser/jsdialog/JavascriptTabModalDialogTest.java",
+  "javatests/src/org/chromium/chrome/browser/language/settings/LanguageSettingsTest.java",
   "javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java",
   "javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperUtils.java",
   "javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java",
@@ -457,7 +458,6 @@
   "javatests/src/org/chromium/chrome/browser/services/GoogleServicesManagerIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java",
   "javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java",
-  "javatests/src/org/chromium/chrome/browser/settings/language/LanguageSettingsTest.java",
   "javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java",
   "javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java",
   "javatests/src/org/chromium/chrome/browser/share/ShareButtonControllerTest.java",
diff --git a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
index eaaebd3..3e491f2 100644
--- a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
+++ b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
@@ -331,7 +331,7 @@
 }
 
 ################################################################################
-# ../../chrome/android/java/proguard.flags
+# ../../chrome/android/proguard/main.flags
 ################################################################################
 # Copyright 2016 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
index 979be8b2..4526d00 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
@@ -20,6 +20,7 @@
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.tab_management.suggestions.TabSuggestion.TabSuggestionAction;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -254,23 +255,35 @@
             Log.e(TAG, "TabSuggestionFeedback is null");
             return;
         }
+
+        String suffix = "";
+        switch (tabSuggestionFeedback.tabSuggestion.getAction()) {
+            case TabSuggestionAction.CLOSE:
+                suffix = "Closing";
+                break;
+            case TabSuggestionAction.GROUP:
+                suffix = "Grouping";
+                break;
+            default:
+                assert false : "Unknown TabSuggestion action";
+        }
+
         // Record TabSuggestionFeedback for testing purposes
         mTabSuggestionFeedback = tabSuggestionFeedback;
 
-        if (tabSuggestionFeedback.tabSuggestionResponse
-                == TabSuggestionFeedback.TabSuggestionResponse.NOT_CONSIDERED) {
-            RecordUserAction.record("TabsSuggestions.Close.SuggestionsReview.Dismissed");
-            recordDismissalBackoff();
-            return;
-        } else {
-            RecordUserAction.record("TabsSuggestions.Close.SuggestionsReview.Accepted");
-            if (tabSuggestionFeedback.tabSuggestionResponse
-                    == TabSuggestionFeedback.TabSuggestionResponse.ACCEPTED) {
-                RecordUserAction.record("TabsSuggestions.Close.Accepted");
-            } else {
-                RecordUserAction.record("TabsSuggestions.Close.Dismissed");
+        switch (tabSuggestionFeedback.tabSuggestionResponse) {
+            case TabSuggestionFeedback.TabSuggestionResponse.NOT_CONSIDERED:
+                RecordUserAction.record("TabsSuggestions.NotConsidered." + suffix);
+                recordDismissalBackoff();
                 return;
-            }
+            case TabSuggestionFeedback.TabSuggestionResponse.ACCEPTED:
+                RecordUserAction.record("TabsSuggestions.Considered.Accepted." + suffix);
+                break;
+            case TabSuggestionFeedback.TabSuggestionResponse.DISMISSED:
+                RecordUserAction.record("TabsSuggestions.Considered.Dismissed." + suffix);
+                return;
+            default:
+                assert false : "Unknown TabSuggestionResponse";
         }
 
         Set<Integer> suggestedTabIds = new HashSet<>();
@@ -289,8 +302,8 @@
         }
         int numChanged = tabSuggestionFeedback.tabSuggestion.getTabsInfo().size()
                 - numSelectFromSuggestion + numSelectOutsideSuggestion;
-        // This was previously TabsSuggestions.Close.NumSuggestionsChanged
+        // This was previously TabsSuggestions.Close.NumSuggestionsChanged.
         RecordHistogram.recordCount100Histogram(
-                "Tabs.Suggestions.Close.NumSuggestionsChanged", numChanged);
+                "Tabs.Suggestions.NumSuggestionsChanged." + suffix, numChanged);
     }
 }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index 1bb97f2..4c39d9b 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -73,6 +73,7 @@
     private final View mNtpHeader;
     private final boolean mShowDarkBackground;
     private final boolean mIsPlaceholderShown;
+    private final boolean mV2Enabled;
     private final FeedSurfaceDelegate mDelegate;
     private final int mDefaultMargin;
     private final int mWideMargin;
@@ -216,6 +217,8 @@
         mSectionHeaderView = sectionHeaderView;
         mShowDarkBackground = showDarkBackground;
         mIsPlaceholderShown = isPlaceholderShown;
+        mV2Enabled = FeatureList.isInitialized()
+                && ChromeFeatureList.isEnabled(ChromeFeatureList.INTEREST_FEED_V2);
         mDelegate = delegate;
         mPageNavigationDelegate = pageNavigationDelegate;
         mBottomSheetController = bottomSheetController;
@@ -223,9 +226,12 @@
         mActionOptions = actionOptions;
 
         Resources resources = mActivity.getResources();
-        mDefaultMargin =
-                resources.getDimensionPixelSize(R.dimen.content_suggestions_card_modern_margin);
-        mWideMargin = resources.getDimensionPixelSize(R.dimen.ntp_wide_card_lateral_margins);
+        mDefaultMargin = resources.getDimensionPixelSize(mV2Enabled
+                        ? R.dimen.content_suggestions_card_modern_margin_v2
+                        : R.dimen.content_suggestions_card_modern_margin);
+        mWideMargin = resources.getDimensionPixelSize(mV2Enabled
+                        ? R.dimen.ntp_wide_card_lateral_margins_v2
+                        : R.dimen.ntp_wide_card_lateral_margins);
 
         mRootView = new RootView(mActivity);
         mRootView.setPadding(0, resources.getDimensionPixelOffset(R.dimen.tab_strip_height), 0, 0);
@@ -308,9 +314,7 @@
             mScrollViewResizer = null;
         }
 
-        boolean v2Enabled = FeatureList.isInitialized()
-                && ChromeFeatureList.isEnabled(ChromeFeatureList.INTEREST_FEED_V2);
-        if (v2Enabled) {
+        if (mV2Enabled) {
             mStream = new FeedStream(mActivity, mShowDarkBackground, mSnackbarManager,
                     mPageNavigationDelegate, mBottomSheetController);
         } else {
@@ -352,7 +356,7 @@
             mStream.setHeaderViews(Arrays.asList(new NonDismissibleHeader(mSectionHeaderView)));
         }
 
-        if (!v2Enabled) {
+        if (!mV2Enabled) {
             mStream.addScrollListener(new FeedLoggingBridge.ScrollEventReporter(
                     FeedProcessScopeFactory.getFeedLoggingBridge()));
         }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
index 42eb2d5..faae547 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.ntp.snippets.SectionHeader;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
@@ -290,8 +289,7 @@
     private boolean createSignInPromoIfNeeded() {
         if (!SignInPromo.shouldCreatePromo()) return false;
         if (mSignInPromo == null) {
-            boolean suggestionsVisible =
-                    PrefServiceBridge.getInstance().getBoolean(Pref.ARTICLES_LIST_VISIBLE);
+            boolean suggestionsVisible = getPrefService().getBoolean(Pref.ARTICLES_LIST_VISIBLE);
 
             mSignInPromo = new FeedSignInPromo(mSigninManager);
             mSignInPromo.setCanShowPersonalizedSuggestions(suggestionsVisible);
diff --git a/chrome/android/java/OWNERS b/chrome/android/java/OWNERS
index e2d6f30..c3f9d22 100644
--- a/chrome/android/java/OWNERS
+++ b/chrome/android/java/OWNERS
@@ -1,2 +1 @@
-per-file *.flags=smaier@chromium.org
 per-file *.grd*=twellington@chromium.org
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 7c0d51c2d..fc029ee 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -354,9 +354,11 @@
          (matches toolbar_height_no_shadow). -->
     <dimen name="ntp_search_box_bounds_vertical_inset_modern">-4dp</dimen>
     <dimen name="ntp_wide_card_lateral_margins">48dp</dimen>
+    <dimen name="ntp_wide_card_lateral_margins_v2">36dp</dimen>
     <dimen name="snippets_article_header_height">40dp</dimen>
-    <!-- This is in sp because we want the icon to scale with the TextView it sits alongside. -->
     <dimen name="content_suggestions_card_modern_margin">12dp</dimen>
+    <dimen name="content_suggestions_card_modern_margin_v2">0dp</dimen>
+    <!-- This is in sp because we want the icon to scale with the TextView it sits alongside. -->
     <dimen name="md_incognito_ntp_line_spacing">6sp</dimen>
     <dimen name="md_incognito_ntp_padding_left">16dp</dimen>
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPromoHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPromoHeader.java
index ef1940e..cfbb76c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPromoHeader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPromoHeader.java
@@ -211,7 +211,7 @@
             return sPromoStateForTests;
         }
 
-        if (!AndroidSyncSettings.get().isMasterSyncEnabled()) {
+        if (!AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync()) {
             return PromoState.PROMO_NONE;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java
index d184353..4f4850c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java
@@ -22,7 +22,6 @@
  */
 public class InstalledWebappBridge {
     private static long sNativeInstalledWebappProvider;
-    private static long sNativePermissionResultCallback;
 
     /**
      * A POD class to store the combination of a permission setting and the origin the permission is
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdater.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdater.java
index 6d77d877..fe9dcda 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdater.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdater.java
@@ -61,13 +61,18 @@
     void checkPermission(Origin origin, long callback) {
         mTrustedWebActivityClient.checkLocationPermission(
                 origin, new TrustedWebActivityClient.PermissionCheckCallback() {
+                    private boolean mCalled;
                     @Override
                     public void onPermissionCheck(ComponentName answeringApp, boolean enabled) {
+                        if (mCalled) return;
+                        mCalled = true;
                         updatePermission(origin, callback, answeringApp, enabled);
                     }
 
                     @Override
                     public void onNoTwaFound() {
+                        if (mCalled) return;
+                        mCalled = true;
                         mPermissionManager.resetStoredPermission(origin, TYPE);
                         InstalledWebappBridge.onGetPermissionResult(callback, false);
                     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
index a5bd3cc..26dbd33 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -75,10 +75,6 @@
         mSearchPanel = panel;
     }
 
-    // TODO(donnd): Consider adding a test-only constructor that uses dependency injection of a
-    // preference manager and PrefServiceBridge.  Currently this is not possible because the
-    // PrefServiceBridge is final.
-
     /**
      * @return The number of additional times to show the promo on tap, 0 if it should not be shown,
      *         or a negative value if the counter has been disabled or the user has accepted
@@ -489,7 +485,6 @@
      *         on enabling or disabling the feature.
      */
     boolean isUserUndecided() {
-        // TODO(donnd) use dependency injection for the PrefServiceBridge instead!
         if (mDidOverrideDecidedStateForTesting) return !mDecidedStateForTesting;
 
         return ContextualSearchManager.isContextualSearchUninitialized();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
index f7efaf2..a3fde14 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
@@ -48,7 +48,6 @@
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
 import org.chromium.components.offline_items_collection.OfflineItemShareInfo;
-import org.chromium.components.offline_items_collection.OfflineItemState;
 import org.chromium.components.offline_items_collection.VisualsCallback;
 
 import java.io.Closeable;
@@ -373,11 +372,7 @@
         mDeleteController.canDelete(items, delete -> {
             if (delete) {
                 for (OfflineItem item : itemsToDelete) {
-                    if (item.state != OfflineItemState.COMPLETE) {
-                        mProvider.cancelDownload(item);
-                    } else {
-                        mProvider.removeItem(item);
-                    }
+                    mProvider.removeItem(item);
 
                     // Remove and have a single decision path for cleaning up thumbnails when the
                     // glue layer is no longer needed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
index 7ee2459..fc76e81 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
@@ -8,6 +8,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceFragmentCompat;
 
@@ -92,7 +93,8 @@
         startActivityForResult(intent, REQUEST_CODE_ADD_LANGUAGES);
     }
 
-    private PrefService getPrefService() {
+    @VisibleForTesting
+    static PrefService getPrefService() {
         return UserPrefs.get(Profile.getLastUsedRegularProfile());
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index 2b1ed01e..cf9d0ae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -38,7 +38,7 @@
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.usage_stats.NotificationSuspender;
@@ -54,6 +54,7 @@
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
 import org.chromium.components.url_formatter.SchemeDisplay;
 import org.chromium.components.url_formatter.UrlFormatter;
+import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.components.webapk.lib.client.WebApkValidator;
 import org.chromium.url.URI;
 import org.chromium.webapk.lib.client.WebApkIdentityServiceClient;
@@ -469,7 +470,7 @@
      * @param scopeUrl The scope of the service worker registered by the site where the notification
      *                 comes from.
      * @param profileId Id of the profile that showed the notification.
-     * @param incognito if the session of the profile is an off the record one.
+     * @param profile The profile that showed the notification.
      * @param title Title to be displayed in the notification.
      * @param body Message to be displayed in the notification. Will be trimmed to one line of
      *             text by the Android notification system.
@@ -490,16 +491,19 @@
     @CalledByNative
     private void displayNotification(final String notificationId,
             @NotificationType final int notificationType, final String origin,
-            final String scopeUrl, final String profileId, final boolean incognito,
+            final String scopeUrl, final String profileId, final Profile profile,
             final String title, final String body, final Bitmap image, final Bitmap icon,
             final Bitmap badge, final int[] vibrationPattern, final long timestamp,
             final boolean renotify, final boolean silent, final ActionInfo[] actions) {
+        final boolean vibrateEnabled = UserPrefs.get(Profile.getLastUsedRegularProfile())
+                                               .getBoolean(NOTIFICATIONS_VIBRATE_ENABLED);
+        final boolean incognito = profile.isOffTheRecord();
         // TODO(peter): by-pass this check for non-Web Notification types.
         getWebApkPackage(scopeUrl).then(
                 (Callback<String>) (webApkPackage)
                         -> displayNotificationInternal(notificationId, notificationType, origin,
-                                scopeUrl, profileId, incognito, title, body, image, icon, badge,
-                                vibrationPattern, timestamp, renotify, silent, actions,
+                                scopeUrl, profileId, incognito, vibrateEnabled, title, body, image,
+                                icon, badge, vibrationPattern, timestamp, renotify, silent, actions,
                                 webApkPackage));
     }
 
@@ -517,18 +521,19 @@
     /** Called after querying whether the browser backs the given WebAPK. */
     private void displayNotificationInternal(String notificationId,
             @NotificationType int notificationType, String origin, String scopeUrl,
-            String profileId, boolean incognito, String title, String body, Bitmap image,
-            Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp, boolean renotify,
-            boolean silent, ActionInfo[] actions, String webApkPackage) {
+            String profileId, boolean incognito, boolean vibrateEnabled, String title, String body,
+            Bitmap image, Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp,
+            boolean renotify, boolean silent, ActionInfo[] actions, String webApkPackage) {
         NotificationPlatformBridgeJni.get().storeCachedWebApkPackageForNotificationId(
                 mNativeNotificationPlatformBridge, NotificationPlatformBridge.this, notificationId,
                 webApkPackage);
         // Record whether it's known whether notifications can be shown to the user at all.
         NotificationSystemStatusUtil.recordAppNotificationStatusHistogram();
 
-        NotificationBuilderBase notificationBuilder = prepareNotificationBuilder(notificationId,
-                notificationType, origin, scopeUrl, profileId, incognito, title, body, image, icon,
-                badge, vibrationPattern, timestamp, renotify, silent, actions, webApkPackage);
+        NotificationBuilderBase notificationBuilder =
+                prepareNotificationBuilder(notificationId, notificationType, origin, scopeUrl,
+                        profileId, incognito, vibrateEnabled, title, body, image, icon, badge,
+                        vibrationPattern, timestamp, renotify, silent, actions, webApkPackage);
 
         // Delegate notification to WebAPK.
         if (!webApkPackage.isEmpty()) {
@@ -569,9 +574,9 @@
 
     private NotificationBuilderBase prepareNotificationBuilder(String notificationId,
             @NotificationType int notificationType, String origin, String scopeUrl,
-            String profileId, boolean incognito, String title, String body, Bitmap image,
-            Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp, boolean renotify,
-            boolean silent, ActionInfo[] actions, String webApkPackage) {
+            String profileId, boolean incognito, boolean vibrateEnabled, String title, String body,
+            Bitmap image, Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp,
+            boolean renotify, boolean silent, ActionInfo[] actions, String webApkPackage) {
         Context context = ContextUtils.getApplicationContext();
 
         PendingIntentProvider clickIntent = makePendingIntent(context,
@@ -628,8 +633,6 @@
         // The Android framework applies a fallback vibration pattern for the sound when the device
         // is in vibrate mode, there is no custom pattern, and the vibration default has been
         // disabled. To truly prevent vibration, provide a custom empty pattern.
-        boolean vibrateEnabled =
-                PrefServiceBridge.getInstance().getBoolean(NOTIFICATIONS_VIBRATE_ENABLED);
         if (!vibrateEnabled) {
             vibrationPattern = EMPTY_VIBRATION_PATTERN;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index 0fac23d..80668fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -324,8 +324,6 @@
     private final String mMerchantName;
     @Nullable
     private final byte[][] mCertificateChain;
-    private final AddressEditor mAddressEditor;
-    private final CardEditor mCardEditor;
     private final JourneyLogger mJourneyLogger;
     private final boolean mIsOffTheRecord;
 
@@ -379,19 +377,13 @@
     private String mId;
     private Map<String, PaymentMethodData> mMethodData;
     private int mShippingType;
-    private SectionInformation mShippingAddressesSection;
-    private ContactDetailsSection mContactSection;
     private boolean mIsFinishedQueryingPaymentApps;
-    private AutofillPaymentAppCreator mAutofillPaymentAppCreator;
     private List<PaymentApp> mPendingApps = new ArrayList<>();
-    private SectionInformation mPaymentMethodsSection;
     private final PaymentUIsManager mPaymentUIsManager;
     private MinimalUICoordinator mMinimalUi;
     private Callback<PaymentInformation> mPaymentInformationCallback;
     private PaymentApp mInvokedPaymentApp;
     private PaymentHandlerCoordinator mPaymentHandlerUi;
-    private boolean mMerchantSupportsAutofillCards;
-    private boolean mUserCanAddCreditCard;
     private boolean mHideServerAutofillCards;
     private ContactEditor mContactEditor;
     private boolean mHasRecordedAbortReason;
@@ -499,12 +491,12 @@
         mIsOffTheRecord = mDelegate.isOffTheRecord(ChromeActivity.fromWebContents(mWebContents));
 
         // Do not persist changes on disk in OffTheRecord mode.
-        mAddressEditor = new AddressEditor(
+        AddressEditor addressEditor = new AddressEditor(
                 AddressEditor.Purpose.PAYMENT_REQUEST, /*saveToDisk=*/!mIsOffTheRecord);
         // PaymentRequest card editor does not show the organization name in the dropdown with the
         // billing address labels.
-        mCardEditor = new CardEditor(
-                mWebContents, mAddressEditor, /*includeOrgLabel=*/false, sObserverForTest);
+        CardEditor cardEditor = new CardEditor(
+                mWebContents, addressEditor, /*includeOrgLabel=*/false, sObserverForTest);
 
         mJourneyLogger = new JourneyLogger(mIsOffTheRecord, mWebContents);
         mCurrencyFormatterMap = new HashMap<>();
@@ -512,7 +504,7 @@
         mSkipUiForNonUrlPaymentMethodIdentifiers = mDelegate.skipUiForBasicCard();
 
         if (sObserverForTest != null) sObserverForTest.onPaymentRequestCreated(this);
-        mPaymentUIsManager = new PaymentUIsManager();
+        mPaymentUIsManager = new PaymentUIsManager(addressEditor, cardEditor);
         mPaymentAppComparator = new PaymentAppComparator(/*paramsProvider=*/this);
     }
 
@@ -581,7 +573,8 @@
         boolean googlePayBridgeActivated = googlePayBridgeEligible
                 && SkipToGPayHelper.canActivateExperiment(mWebContents, methodData);
 
-        mMethodData = getValidatedMethodData(methodData, googlePayBridgeActivated, mCardEditor);
+        mMethodData = getValidatedMethodData(
+                methodData, googlePayBridgeActivated, mPaymentUIsManager.getCardEditor());
         if (mMethodData == null) {
             mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_METHODS_OR_DATA);
@@ -616,13 +609,14 @@
         mId = details.id;
 
         // Checks whether the merchant supports autofill cards before show is called.
-        mMerchantSupportsAutofillCards =
+        boolean merchantSupportsAutofillCards =
                 AutofillPaymentAppFactory.merchantSupportsBasicCard(mMethodData);
         // If in strict mode, don't give user an option to add an autofill card during the checkout
         // to avoid the "unhappy" basic-card flow.
-        mUserCanAddCreditCard = mMerchantSupportsAutofillCards
+        mPaymentUIsManager.setCanUserAddCreditCard(merchantSupportsAutofillCards
                 && !PaymentFeatureList.isEnabledOrExperimentalFeaturesEnabled(
-                        PaymentFeatureList.STRICT_HAS_ENROLLED_AUTOFILL_INSTRUMENT);
+                        PaymentFeatureList.STRICT_HAS_ENROLLED_AUTOFILL_INSTRUMENT));
+        mPaymentUIsManager.setMerchantSupportsAutofillCards(merchantSupportsAutofillCards);
 
         if (mRequestShipping || mRequestPayerName || mRequestPayerPhone || mRequestPayerEmail) {
             mAutofillProfiles = Collections.unmodifiableList(
@@ -665,8 +659,8 @@
         // Log the various types of payment methods that were requested by the merchant.
         boolean requestedMethodGoogle = false;
         // Not to record requestedMethodBasicCard because JourneyLogger ignore the case where the
-        // specified networks are unsupported. mMerchantSupportsAutofillCards better
-        // captures this group of interest than requestedMethodBasicCard.
+        // specified networks are unsupported. mPaymentUIsManager.isMerchantSupportsAutofillCards()
+        // better captures this group of interest than requestedMethodBasicCard.
         boolean requestedMethodOther = false;
         mURLPaymentMethodIdentifiersSupported = false;
         for (String methodName : mMethodData.keySet()) {
@@ -678,7 +672,7 @@
                     break;
                 case MethodStrings.BASIC_CARD:
                     // Not to record requestedMethodBasicCard because
-                    // mMerchantSupportsAutofillCards is used instead.
+                    // mPaymentUIsManager.isMerchantSupportsAutofillCards() is used instead.
                     break;
                 default:
                     // "Other" includes https url, http url(when certifate check is bypassed) and
@@ -691,8 +685,8 @@
             }
         }
         mJourneyLogger.setRequestedPaymentMethodTypes(
-                /*requestedBasicCard=*/mMerchantSupportsAutofillCards, requestedMethodGoogle,
-                requestedMethodOther);
+                /*requestedBasicCard=*/mPaymentUIsManager.merchantSupportsAutofillCards(),
+                requestedMethodGoogle, requestedMethodOther);
     }
 
     /**
@@ -704,8 +698,9 @@
         assert mIsFinishedQueryingPaymentApps;
         assert mIsCurrentPaymentRequestShowing;
 
-        assert mPaymentMethodsSection != null;
-        PaymentApp selectedApp = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+        assert mPaymentUIsManager.getPaymentMethodsSection() != null;
+        PaymentApp selectedApp =
+                (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
 
         // If there is only a single payment app which can provide all merchant requested
         // information, we can safely go directly to the payment app instead of showing Payment
@@ -717,7 +712,7 @@
                 // the payment request UI, thus can't be skipped.
                 && (mURLPaymentMethodIdentifiersSupported
                         || mSkipUiForNonUrlPaymentMethodIdentifiers)
-                && mPaymentMethodsSection.getSize() >= 1
+                && mPaymentUIsManager.getPaymentMethodsSection().getSize() >= 1
                 && onlySingleAppCanProvideAllRequiredInformation()
                 // Skip to payment app only if it can be pre-selected.
                 && selectedApp != null
@@ -731,17 +726,18 @@
      * information including shipping address and payer's contact information whenever needed.
      */
     private boolean onlySingleAppCanProvideAllRequiredInformation() {
-        assert mPaymentMethodsSection != null;
+        assert mPaymentUIsManager.getPaymentMethodsSection() != null;
 
         if (!mRequestShipping && !mRequestPayerName && !mRequestPayerPhone && !mRequestPayerEmail) {
-            return mPaymentMethodsSection.getSize() == 1
-                    && !((PaymentApp) mPaymentMethodsSection.getItem(0)).isAutofillInstrument();
+            return mPaymentUIsManager.getPaymentMethodsSection().getSize() == 1
+                    && !((PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getItem(0))
+                                .isAutofillInstrument();
         }
 
         boolean anAppCanProvideAllInfo = false;
-        int sectionSize = mPaymentMethodsSection.getSize();
+        int sectionSize = mPaymentUIsManager.getPaymentMethodsSection().getSize();
         for (int i = 0; i < sectionSize; i++) {
-            PaymentApp app = (PaymentApp) mPaymentMethodsSection.getItem(i);
+            PaymentApp app = (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getItem(i);
             if ((!mRequestShipping || app.handlesShippingAddress())
                     && (!mRequestPayerName || app.handlesPayerName())
                     && (!mRequestPayerPhone || app.handlesPayerPhone())
@@ -762,7 +758,7 @@
         // shipping and contact sections (when requested by merchant) are populated depending on
         // whether or not the selected payment app (if such exists) can provide the required
         // information.
-        assert mPaymentMethodsSection != null;
+        assert mPaymentUIsManager.getPaymentMethodsSection() != null;
 
         assert activity != null;
 
@@ -798,13 +794,13 @@
         }
 
         if (shouldShowContactSection()) {
-            mContactSection = new ContactDetailsSection(
-                    activity, mAutofillProfiles, mContactEditor, mJourneyLogger);
+            mPaymentUIsManager.setContactSection(new ContactDetailsSection(
+                    activity, mAutofillProfiles, mContactEditor, mJourneyLogger));
         }
 
         mPaymentUIsManager.setPaymentRequestUI(new PaymentRequestUI(activity, this,
-                mMerchantSupportsAutofillCards, !PaymentPreferencesUtil.isPaymentCompleteOnce(),
-                mMerchantName, mTopLevelOrigin,
+                mPaymentUIsManager.merchantSupportsAutofillCards(),
+                !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantName, mTopLevelOrigin,
                 SecurityStateModel.getSecurityLevelForWebContents(mWebContents),
                 new ShippingStrings(mShippingType),
                 mPaymentUIsManager.getPaymentUisShowStateReconciler(),
@@ -834,8 +830,10 @@
                     this);
         }
 
-        mAddressEditor.setEditorDialog(mPaymentUIsManager.getPaymentRequestUI().getEditorDialog());
-        mCardEditor.setEditorDialog(mPaymentUIsManager.getPaymentRequestUI().getCardEditorDialog());
+        mPaymentUIsManager.getAddressEditor().setEditorDialog(
+                mPaymentUIsManager.getPaymentRequestUI().getEditorDialog());
+        mPaymentUIsManager.getCardEditor().setEditorDialog(
+                mPaymentUIsManager.getPaymentRequestUI().getCardEditorDialog());
         if (mContactEditor != null) {
             mContactEditor.setEditorDialog(
                     mPaymentUIsManager.getPaymentRequestUI().getEditorDialog());
@@ -850,7 +848,7 @@
 
         for (int i = 0; i < unmodifiableProfiles.size(); i++) {
             AutofillProfile profile = unmodifiableProfiles.get(i);
-            mAddressEditor.addPhoneNumberIfValid(profile.getPhoneNumber());
+            mPaymentUIsManager.getAddressEditor().addPhoneNumberIfValid(profile.getPhoneNumber());
 
             // Only suggest addresses that have a street address.
             if (!TextUtils.isEmpty(profile.getStreetAddress())) {
@@ -905,8 +903,9 @@
                     "PaymentRequest.MissingShippingFields", missingFields);
         }
 
-        mShippingAddressesSection = new SectionInformation(
-                PaymentRequestUI.DataType.SHIPPING_ADDRESSES, firstCompleteAddressIndex, addresses);
+        mPaymentUIsManager.setShippingAddressesSection(
+                new SectionInformation(PaymentRequestUI.DataType.SHIPPING_ADDRESSES,
+                        firstCompleteAddressIndex, addresses));
     }
 
     // Implement ComponentPaymentRequestDelegate:
@@ -956,7 +955,8 @@
         if (mIsFinishedQueryingPaymentApps) {
             // Send AppListReady signal when all apps are created and request.show() is called.
             if (mNativeObserverForTest != null) {
-                mNativeObserverForTest.onAppListReady(mPaymentMethodsSection.getItems(), mRawTotal);
+                mNativeObserverForTest.onAppListReady(
+                        mPaymentUIsManager.getPaymentMethodsSection().getItems(), mRawTotal);
             }
             // Calculate skip ui and build ui only after all payment apps are ready and
             // request.show() is called.
@@ -992,7 +992,7 @@
         if ((mShouldSkipShowingPaymentRequestUi || mSkipToGPayHelper != null)
                 && mIsFinishedQueryingPaymentApps && mIsCurrentPaymentRequestShowing
                 && !mWaitForUpdatedDetails) {
-            assert !mPaymentMethodsSection.isEmpty();
+            assert !mPaymentUIsManager.getPaymentMethodsSection().isEmpty();
             assert mPaymentUIsManager.getPaymentRequestUI() != null;
 
             if (isMinimalUiApplicable()) {
@@ -1000,8 +1000,9 @@
                 return;
             }
 
-            assert !mPaymentMethodsSection.isEmpty();
-            PaymentApp selectedApp = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+            assert !mPaymentUIsManager.getPaymentMethodsSection().isEmpty();
+            PaymentApp selectedApp =
+                    (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
             dimBackgroundIfNotBottomSheetPaymentHandler(selectedApp);
             mDidRecordShowEvent = true;
             mJourneyLogger.setEventOccurred(Event.SKIPPED_SHOW);
@@ -1018,12 +1019,13 @@
 
     /** @return Whether the minimal UI should be shown. */
     private boolean isMinimalUiApplicable() {
-        if (!mIsUserGestureShow || mPaymentMethodsSection == null
-                || mPaymentMethodsSection.getSize() != 1) {
+        if (!mIsUserGestureShow || mPaymentUIsManager.getPaymentMethodsSection() == null
+                || mPaymentUIsManager.getPaymentMethodsSection().getSize() != 1) {
             return false;
         }
 
-        PaymentApp app = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+        PaymentApp app =
+                (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
         if (app == null || !app.isReadyForMinimalUI() || TextUtils.isEmpty(app.accountBalance())) {
             return false;
         }
@@ -1042,7 +1044,7 @@
         mMinimalUi = new MinimalUICoordinator();
         if (mMinimalUi.show(chromeActivity,
                     BottomSheetControllerProvider.from(chromeActivity.getWindowAndroid()),
-                    (PaymentApp) mPaymentMethodsSection.getSelectedItem(),
+                    (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem(),
                     mCurrencyFormatterMap.get(mRawTotal.amount.currency),
                     mUiShoppingCart.getTotal(), this::onMinimalUIReady, this::onMinimalUiConfirmed,
                     this::onMinimalUiDismissed)) {
@@ -1369,10 +1371,11 @@
 
         if (shouldShowShippingSection()
                 && (mUiShippingOptions.isEmpty() || !TextUtils.isEmpty(details.error))
-                && mShippingAddressesSection.getSelectedItem() != null) {
-            mShippingAddressesSection.getSelectedItem().setInvalid();
-            mShippingAddressesSection.setSelectedItemIndex(SectionInformation.INVALID_SELECTION);
-            mShippingAddressesSection.setErrorMessage(details.error);
+                && mPaymentUIsManager.getShippingAddressesSection().getSelectedItem() != null) {
+            mPaymentUIsManager.getShippingAddressesSection().getSelectedItem().setInvalid();
+            mPaymentUIsManager.getShippingAddressesSection().setSelectedItemIndex(
+                    SectionInformation.INVALID_SELECTION);
+            mPaymentUIsManager.getShippingAddressesSection().setErrorMessage(details.error);
         }
 
         enableUserInterfaceAfterPaymentRequestUpdateEvent();
@@ -1447,7 +1450,8 @@
     }
 
     private void enableUserInterfaceAfterPaymentRequestUpdateEvent() {
-        if (mPaymentInformationCallback != null && mPaymentMethodsSection != null) {
+        if (mPaymentInformationCallback != null
+                && mPaymentUIsManager.getPaymentMethodsSection() != null) {
             providePaymentInformation();
         } else {
             mPaymentUIsManager.getPaymentRequestUI().updateOrderSummarySection(mUiShoppingCart);
@@ -1533,10 +1537,10 @@
     private void updateAppModifiedTotals() {
         if (!PaymentFeatureList.isEnabled(PaymentFeatureList.WEB_PAYMENTS_MODIFIERS)) return;
         if (mModifiers == null) return;
-        if (mPaymentMethodsSection == null) return;
+        if (mPaymentUIsManager.getPaymentMethodsSection() == null) return;
 
-        for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) {
-            PaymentApp app = (PaymentApp) mPaymentMethodsSection.getItem(i);
+        for (int i = 0; i < mPaymentUIsManager.getPaymentMethodsSection().getSize(); i++) {
+            PaymentApp app = (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getItem(i);
             PaymentDetailsModifier modifier = getModifier(app);
             app.setModifiedTotal(modifier == null || modifier.total == null
                             ? null
@@ -1544,7 +1548,8 @@
                                       .format(modifier.total.amount.value));
         }
 
-        updateOrderSummary((PaymentApp) mPaymentMethodsSection.getSelectedItem());
+        updateOrderSummary(
+                (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem());
     }
 
     /** Sets the modifier for the order summary based on the given app, if any. */
@@ -1713,11 +1718,13 @@
     private void providePaymentInformation() {
         // Do not display service worker payment apps summary in single line so as to display its
         // origin completely.
-        mPaymentMethodsSection.setDisplaySelectedItemSummaryInSingleLineInNormalMode(
-                getSelectedPaymentAppType() != PaymentAppType.SERVICE_WORKER_APP);
-        mPaymentInformationCallback.onResult(
-                new PaymentInformation(mUiShoppingCart, mShippingAddressesSection,
-                        mUiShippingOptions, mContactSection, mPaymentMethodsSection));
+        mPaymentUIsManager.getPaymentMethodsSection()
+                .setDisplaySelectedItemSummaryInSingleLineInNormalMode(
+                        getSelectedPaymentAppType() != PaymentAppType.SERVICE_WORKER_APP);
+        mPaymentInformationCallback.onResult(new PaymentInformation(mUiShoppingCart,
+                mPaymentUIsManager.getShippingAddressesSection(), mUiShippingOptions,
+                mPaymentUIsManager.getContactSection(),
+                mPaymentUIsManager.getPaymentMethodsSection()));
         mPaymentInformationCallback = null;
 
         if (!mDidRecordShowEvent) {
@@ -1745,16 +1752,16 @@
         SectionInformation result = null;
         switch (optionType) {
             case PaymentRequestUI.DataType.SHIPPING_ADDRESSES:
-                result = mShippingAddressesSection;
+                result = mPaymentUIsManager.getShippingAddressesSection();
                 break;
             case PaymentRequestUI.DataType.SHIPPING_OPTIONS:
                 result = mUiShippingOptions;
                 break;
             case PaymentRequestUI.DataType.CONTACT_DETAILS:
-                result = mContactSection;
+                result = mPaymentUIsManager.getContactSection();
                 break;
             case PaymentRequestUI.DataType.PAYMENT_METHODS:
-                result = mPaymentMethodsSection;
+                result = mPaymentUIsManager.getPaymentMethodsSection();
                 break;
             default:
                 assert false;
@@ -1773,7 +1780,7 @@
             mJourneyLogger.incrementSelectionChanges(Section.SHIPPING_ADDRESS);
             AutofillAddress address = (AutofillAddress) option;
             if (address.isComplete()) {
-                mShippingAddressesSection.setSelectedItem(option);
+                mPaymentUIsManager.getShippingAddressesSection().setSelectedItem(option);
                 startShippingAddressChangeNormalization(address);
             } else {
                 editAddress(address);
@@ -1791,7 +1798,7 @@
             mJourneyLogger.incrementSelectionChanges(Section.CONTACT_INFO);
             AutofillContact contact = (AutofillContact) option;
             if (contact.isComplete()) {
-                mContactSection.setSelectedItem(option);
+                mPaymentUIsManager.getContactSection().setSelectedItem(option);
                 if (!mWasRetryCalled) return PaymentRequestUI.SelectionResult.NONE;
                 dispatchPayerDetailChangeEventIfNeeded(contact.toPayerDetail());
             } else {
@@ -1801,20 +1808,23 @@
             mPaymentInformationCallback = callback;
             return PaymentRequestUI.SelectionResult.ASYNCHRONOUS_VALIDATION;
         } else if (optionType == PaymentRequestUI.DataType.PAYMENT_METHODS) {
-            if (shouldShowShippingSection() && mShippingAddressesSection == null) {
+            if (shouldShowShippingSection()
+                    && mPaymentUIsManager.getShippingAddressesSection() == null) {
                 ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents);
                 assert activity != null;
                 createShippingSection(activity, mAutofillProfiles);
             }
-            if (shouldShowContactSection() && mContactSection == null) {
+            if (shouldShowContactSection() && mPaymentUIsManager.getContactSection() == null) {
                 ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents);
                 assert activity != null;
-                mContactSection = new ContactDetailsSection(
-                        activity, mAutofillProfiles, mContactEditor, mJourneyLogger);
+                mPaymentUIsManager.setContactSection(new ContactDetailsSection(
+                        activity, mAutofillProfiles, mContactEditor, mJourneyLogger));
             }
             mPaymentUIsManager.getPaymentRequestUI().selectedPaymentMethodUpdated(
-                    new PaymentInformation(mUiShoppingCart, mShippingAddressesSection,
-                            mUiShippingOptions, mContactSection, mPaymentMethodsSection));
+                    new PaymentInformation(mUiShoppingCart,
+                            mPaymentUIsManager.getShippingAddressesSection(), mUiShippingOptions,
+                            mPaymentUIsManager.getContactSection(),
+                            mPaymentUIsManager.getPaymentMethodsSection()));
             PaymentApp paymentApp = (PaymentApp) option;
             if (paymentApp instanceof AutofillPaymentInstrument) {
                 AutofillPaymentInstrument card = (AutofillPaymentInstrument) paymentApp;
@@ -1828,7 +1838,7 @@
             mJourneyLogger.incrementSelectionChanges(Section.PAYMENT_METHOD);
 
             updateOrderSummary(paymentApp);
-            mPaymentMethodsSection.setSelectedItem(option);
+            mPaymentUIsManager.getPaymentMethodsSection().setSelectedItem(option);
         }
 
         return PaymentRequestUI.SelectionResult.NONE;
@@ -1888,17 +1898,18 @@
     public boolean shouldShowShippingSection() {
         if (!mRequestShipping) return false;
 
-        if (mPaymentMethodsSection == null) return true;
+        if (mPaymentUIsManager.getPaymentMethodsSection() == null) return true;
 
-        PaymentApp selectedApp = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+        PaymentApp selectedApp =
+                (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
         return selectedApp == null || !selectedApp.handlesShippingAddress();
     }
 
     @Override
     public boolean shouldShowContactSection() {
-        PaymentApp selectedApp = (mPaymentMethodsSection == null)
+        PaymentApp selectedApp = (mPaymentUIsManager.getPaymentMethodsSection() == null)
                 ? null
-                : (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+                : (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
         if (mRequestPayerName && (selectedApp == null || !selectedApp.handlesPayerName())) {
             return true;
         }
@@ -1917,40 +1928,45 @@
             // Log the edit of a shipping address.
             mJourneyLogger.incrementSelectionEdits(Section.SHIPPING_ADDRESS);
         }
-        mAddressEditor.edit(toEdit, new Callback<AutofillAddress>() {
+        mPaymentUIsManager.getAddressEditor().edit(toEdit, new Callback<AutofillAddress>() {
             @Override
             public void onResult(AutofillAddress editedAddress) {
                 if (mPaymentUIsManager.getPaymentRequestUI() == null) return;
 
                 if (editedAddress != null) {
-                    mAddressEditor.setAddressErrors(null);
+                    mPaymentUIsManager.getAddressEditor().setAddressErrors(null);
 
                     // Sets or updates the shipping address label.
                     editedAddress.setShippingAddressLabelWithCountry();
 
-                    mCardEditor.updateBillingAddressIfComplete(editedAddress);
+                    mPaymentUIsManager.getCardEditor().updateBillingAddressIfComplete(
+                            editedAddress);
 
                     // A partial or complete address came back from the editor (could have been from
                     // adding/editing or cancelling out of the edit flow).
                     if (!editedAddress.isComplete()) {
                         // If the address is not complete, unselect it (editor can return incomplete
                         // information when cancelled).
-                        mShippingAddressesSection.setSelectedItemIndex(
+                        mPaymentUIsManager.getShippingAddressesSection().setSelectedItemIndex(
                                 SectionInformation.NO_SELECTION);
                         providePaymentInformation();
                     } else {
                         if (toEdit == null) {
                             // Address is complete and user was in the "Add flow": add an item to
                             // the list.
-                            mShippingAddressesSection.addAndSelectItem(editedAddress);
+                            mPaymentUIsManager.getShippingAddressesSection().addAndSelectItem(
+                                    editedAddress);
                         }
 
-                        if (mContactSection != null) {
-                            // Update |mContactSection| with the new/edited address, which will
-                            // update an existing item or add a new one to the end of the list.
-                            mContactSection.addOrUpdateWithAutofillAddress(editedAddress);
+                        if (mPaymentUIsManager.getContactSection() != null) {
+                            // Update |mPaymentUIsManager.getContactSection()| with the new/edited
+                            // address, which will update an existing item or add a new one to the
+                            // end of the list.
+                            mPaymentUIsManager.getContactSection().addOrUpdateWithAutofillAddress(
+                                    editedAddress);
                             mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                                    PaymentRequestUI.DataType.CONTACT_DETAILS, mContactSection);
+                                    PaymentRequestUI.DataType.CONTACT_DETAILS,
+                                    mPaymentUIsManager.getContactSection());
                         }
 
                         startShippingAddressChangeNormalization(editedAddress);
@@ -1982,11 +1998,12 @@
                     if (!editedContact.isComplete()) {
                         // If the contact is not complete according to the requirements of the flow,
                         // unselect it (editor can return incomplete information when cancelled).
-                        mContactSection.setSelectedItemIndex(SectionInformation.NO_SELECTION);
+                        mPaymentUIsManager.getContactSection().setSelectedItemIndex(
+                                SectionInformation.NO_SELECTION);
                     } else if (toEdit == null) {
                         // Contact is complete and we were in the "Add flow": add an item to the
                         // list.
-                        mContactSection.addAndSelectItem(editedContact);
+                        mPaymentUIsManager.getContactSection().addAndSelectItem(editedContact);
                     } else {
                         dispatchPayerDetailChangeEventIfNeeded(editedContact.toPayerDetail());
                     }
@@ -1997,7 +2014,8 @@
                 // action to take (if a contact was selected in the UI, it will stay selected).
 
                 mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                        PaymentRequestUI.DataType.CONTACT_DETAILS, mContactSection);
+                        PaymentRequestUI.DataType.CONTACT_DETAILS,
+                        mPaymentUIsManager.getContactSection());
 
                 if (!mRetryQueue.isEmpty()) mHandler.post(mRetryQueue.remove());
             }
@@ -2009,7 +2027,7 @@
             // Log the edit of a credit card.
             mJourneyLogger.incrementSelectionEdits(Section.PAYMENT_METHOD);
         }
-        mCardEditor.edit(toEdit, new Callback<AutofillPaymentInstrument>() {
+        mPaymentUIsManager.getCardEditor().edit(toEdit, new Callback<AutofillPaymentInstrument>() {
             @Override
             public void onResult(AutofillPaymentInstrument editedCard) {
                 if (mPaymentUIsManager.getPaymentRequestUI() == null) return;
@@ -2020,11 +2038,11 @@
                     if (!editedCard.isComplete()) {
                         // If the card is not complete, unselect it (editor can return incomplete
                         // information when cancelled).
-                        mPaymentMethodsSection.setSelectedItemIndex(
+                        mPaymentUIsManager.getPaymentMethodsSection().setSelectedItemIndex(
                                 SectionInformation.NO_SELECTION);
                     } else if (toEdit == null) {
                         // Card is complete and we were in the "Add flow": add an item to the list.
-                        mPaymentMethodsSection.addAndSelectItem(editedCard);
+                        mPaymentUIsManager.getPaymentMethodsSection().addAndSelectItem(editedCard);
                     }
                     // If card is complete and (toEdit != null), no action needed: the card was
                     // already selected in the UI.
@@ -2035,7 +2053,8 @@
 
                 updateAppModifiedTotals();
                 mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                        PaymentRequestUI.DataType.PAYMENT_METHODS, mPaymentMethodsSection);
+                        PaymentRequestUI.DataType.PAYMENT_METHODS,
+                        mPaymentUIsManager.getPaymentMethodsSection());
             }
         });
     }
@@ -2053,8 +2072,10 @@
     }
 
     private @PaymentAppType int getSelectedPaymentAppType() {
-        return mPaymentMethodsSection != null && mPaymentMethodsSection.getSelectedItem() != null
-                ? ((PaymentApp) mPaymentMethodsSection.getSelectedItem()).getPaymentAppType()
+        return mPaymentUIsManager.getPaymentMethodsSection() != null
+                        && mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem() != null
+                ? ((PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem())
+                          .getPaymentAppType()
                 : PaymentAppType.UNDEFINED;
     }
 
@@ -2063,8 +2084,9 @@
             EditableOption selectedShippingOption, EditableOption selectedPaymentMethod) {
         mInvokedPaymentApp = (PaymentApp) selectedPaymentMethod;
 
-        EditableOption selectedContact =
-                mContactSection != null ? mContactSection.getSelectedItem() : null;
+        EditableOption selectedContact = mPaymentUIsManager.getContactSection() != null
+                ? mPaymentUIsManager.getContactSection().getSelectedItem()
+                : null;
         mPaymentResponseHelper = new PaymentResponseHelper(selectedShippingAddress,
                 selectedShippingOption, selectedContact, mInvokedPaymentApp, mPaymentOptions,
                 mSkipToGPayHelper != null, this);
@@ -2220,7 +2242,8 @@
         }
 
         /** Update records of the used payment app for sorting payment apps next time. */
-        EditableOption selectedPaymentMethod = mPaymentMethodsSection.getSelectedItem();
+        EditableOption selectedPaymentMethod =
+                mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
         PaymentPreferencesUtil.increasePaymentAppUseCount(selectedPaymentMethod.getIdentifier());
         PaymentPreferencesUtil.setPaymentAppLastUseDate(
                 selectedPaymentMethod.getIdentifier(), System.currentTimeMillis());
@@ -2257,13 +2280,16 @@
         mWasRetryCalled = true;
 
         // Remove all payment apps except the selected one.
-        assert mPaymentMethodsSection != null;
-        PaymentApp selectedApp = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+        assert mPaymentUIsManager.getPaymentMethodsSection() != null;
+        PaymentApp selectedApp =
+                (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
         assert selectedApp != null;
-        mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.DataType.PAYMENT_METHODS,
-                /* selection = */ 0, new ArrayList<>(Arrays.asList(selectedApp)));
+        mPaymentUIsManager.setPaymentMethodsSection(
+                new SectionInformation(PaymentRequestUI.DataType.PAYMENT_METHODS,
+                        /* selection = */ 0, new ArrayList<>(Arrays.asList(selectedApp))));
         mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                PaymentRequestUI.DataType.PAYMENT_METHODS, mPaymentMethodsSection);
+                PaymentRequestUI.DataType.PAYMENT_METHODS,
+                mPaymentUIsManager.getPaymentMethodsSection());
         mPaymentUIsManager.getPaymentRequestUI().disableAddingNewCardsDuringRetry();
 
         // Go back to the payment sheet
@@ -2279,9 +2305,10 @@
 
         if (shouldShowShippingSection() && hasShippingAddressError(errors.shippingAddress)) {
             mRetryQueue.add(() -> {
-                mAddressEditor.setAddressErrors(errors.shippingAddress);
+                mPaymentUIsManager.getAddressEditor().setAddressErrors(errors.shippingAddress);
                 AutofillAddress selectedAddress =
-                        (AutofillAddress) mShippingAddressesSection.getSelectedItem();
+                        (AutofillAddress) mPaymentUIsManager.getShippingAddressesSection()
+                                .getSelectedItem();
                 editAddress(selectedAddress);
             });
         }
@@ -2290,7 +2317,7 @@
             mRetryQueue.add(() -> {
                 mContactEditor.setPayerErrors(errors.payer);
                 AutofillContact selectedContact =
-                        (AutofillContact) mContactSection.getSelectedItem();
+                        (AutofillContact) mPaymentUIsManager.getContactSection().getSelectedItem();
                 editContact(selectedContact);
             });
         }
@@ -2330,18 +2357,20 @@
         if (getClient() == null) return;
 
         address.setShippingAddressLabelWithCountry();
-        mCardEditor.updateBillingAddressIfComplete(address);
+        mPaymentUIsManager.getCardEditor().updateBillingAddressIfComplete(address);
 
-        if (mShippingAddressesSection != null) {
-            mShippingAddressesSection.addAndSelectOrUpdateItem(address);
+        if (mPaymentUIsManager.getShippingAddressesSection() != null) {
+            mPaymentUIsManager.getShippingAddressesSection().addAndSelectOrUpdateItem(address);
             mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                    PaymentRequestUI.DataType.SHIPPING_ADDRESSES, mShippingAddressesSection);
+                    PaymentRequestUI.DataType.SHIPPING_ADDRESSES,
+                    mPaymentUIsManager.getShippingAddressesSection());
         }
 
-        if (mContactSection != null) {
-            mContactSection.addOrUpdateWithAutofillAddress(address);
+        if (mPaymentUIsManager.getContactSection() != null) {
+            mPaymentUIsManager.getContactSection().addOrUpdateWithAutofillAddress(address);
             mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                    PaymentRequestUI.DataType.CONTACT_DETAILS, mContactSection);
+                    PaymentRequestUI.DataType.CONTACT_DETAILS,
+                    mPaymentUIsManager.getContactSection());
         }
     }
 
@@ -2349,47 +2378,54 @@
     public void onAddressDeleted(String guid) {
         if (getClient() == null) return;
 
-        // TODO: Delete the address from mShippingAddressesSection and mContactSection. Note that we
-        // only displayed SUGGESTIONS_LIMIT addresses, so we may want to add back previously
-        // ignored addresses.
+        // TODO: Delete the address from mPaymentUIsManager.getShippingAddressesSection() and
+        // mPaymentUIsManager.getContactSection(). Note that we only displayed SUGGESTIONS_LIMIT
+        // addresses, so we may want to add back previously ignored addresses.
     }
 
     @Override
     public void onCreditCardUpdated(CreditCard card) {
-        if (getClient() == null || !mMerchantSupportsAutofillCards || mPaymentMethodsSection == null
-                || mAutofillPaymentAppCreator == null) {
+        if (getClient() == null || !mPaymentUIsManager.merchantSupportsAutofillCards()
+                || mPaymentUIsManager.getPaymentMethodsSection() == null
+                || mPaymentUIsManager.getAutofillPaymentAppCreator() == null) {
             return;
         }
 
-        PaymentApp updatedAutofillCard = mAutofillPaymentAppCreator.createPaymentAppForCard(card);
+        PaymentApp updatedAutofillCard =
+                mPaymentUIsManager.getAutofillPaymentAppCreator().createPaymentAppForCard(card);
 
         // Can be null when the card added through settings does not match the requested card
         // network or is invalid, because autofill settings do not perform the same level of
         // validation as Basic Card implementation in Chrome.
         if (updatedAutofillCard == null) return;
 
-        mPaymentMethodsSection.addAndSelectOrUpdateItem(updatedAutofillCard);
+        mPaymentUIsManager.getPaymentMethodsSection().addAndSelectOrUpdateItem(updatedAutofillCard);
 
         updateAppModifiedTotals();
 
         if (mPaymentUIsManager.getPaymentRequestUI() != null) {
             mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                    PaymentRequestUI.DataType.PAYMENT_METHODS, mPaymentMethodsSection);
+                    PaymentRequestUI.DataType.PAYMENT_METHODS,
+                    mPaymentUIsManager.getPaymentMethodsSection());
         }
     }
 
     @Override
     public void onCreditCardDeleted(String guid) {
         if (getClient() == null) return;
-        if (!mMerchantSupportsAutofillCards || mPaymentMethodsSection == null) return;
+        if (!mPaymentUIsManager.merchantSupportsAutofillCards()
+                || mPaymentUIsManager.getPaymentMethodsSection() == null) {
+            return;
+        }
 
-        mPaymentMethodsSection.removeAndUnselectItem(guid);
+        mPaymentUIsManager.getPaymentMethodsSection().removeAndUnselectItem(guid);
 
         updateAppModifiedTotals();
 
         if (mPaymentUIsManager.getPaymentRequestUI() != null) {
             mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                    PaymentRequestUI.DataType.PAYMENT_METHODS, mPaymentMethodsSection);
+                    PaymentRequestUI.DataType.PAYMENT_METHODS,
+                    mPaymentUIsManager.getPaymentMethodsSection());
         }
     }
 
@@ -2570,7 +2606,7 @@
     // PaymentAppFactoryParams implementation.
     @Override
     public boolean getMayCrawl() {
-        return !mUserCanAddCreditCard
+        return !mPaymentUIsManager.canUserAddCreditCard()
                 || PaymentFeatureList.isEnabledOrExperimentalFeaturesEnabled(
                         PaymentFeatureList.WEB_PAYMENTS_ALWAYS_ALLOW_JUST_IN_TIME_PAYMENT_APP);
     }
@@ -2622,7 +2658,7 @@
     // PaymentAppFactoryDelegate implementation.
     @Override
     public void onAutofillPaymentAppCreatorAvailable(AutofillPaymentAppCreator creator) {
-        mAutofillPaymentAppCreator = creator;
+        mPaymentUIsManager.setAutofillPaymentAppCreator(creator);
     }
 
     // PaymentAppFactoryDelegate implementation.
@@ -2712,8 +2748,9 @@
         }
 
         // The list of payment apps is ready to display.
-        mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.DataType.PAYMENT_METHODS,
-                selection, new ArrayList<>(mPendingApps));
+        mPaymentUIsManager.setPaymentMethodsSection(
+                new SectionInformation(PaymentRequestUI.DataType.PAYMENT_METHODS, selection,
+                        new ArrayList<>(mPendingApps)));
 
         // Record the number suggested payment methods and whether at least one of them was
         // complete.
@@ -2722,7 +2759,7 @@
 
         int missingFields = 0;
         if (mPendingApps.isEmpty()) {
-            if (mMerchantSupportsAutofillCards) {
+            if (mPaymentUIsManager.merchantSupportsAutofillCards()) {
                 // Record all fields if basic-card is supported but no card exists.
                 missingFields = AutofillPaymentInstrument.CompletionStatus.CREDIT_CARD_EXPIRED
                         | AutofillPaymentInstrument.CompletionStatus.CREDIT_CARD_NO_CARDHOLDER
@@ -2746,7 +2783,8 @@
         if (mIsCurrentPaymentRequestShowing) {
             // Send AppListReady signal when all apps are created and request.show() is called.
             if (mNativeObserverForTest != null) {
-                mNativeObserverForTest.onAppListReady(mPaymentMethodsSection.getItems(), mRawTotal);
+                mNativeObserverForTest.onAppListReady(
+                        mPaymentUIsManager.getPaymentMethodsSection().getItems(), mRawTotal);
             }
             // Calculate skip ui and build ui only after all payment apps are ready and
             // request.show() is called.
@@ -2768,9 +2806,11 @@
         if (!mIsFinishedQueryingPaymentApps || !mIsCurrentPaymentRequestShowing) return false;
 
         boolean havePaymentApps = !mPendingApps.isEmpty()
-                || (mPaymentMethodsSection != null && !mPaymentMethodsSection.isEmpty());
+                || (mPaymentUIsManager.getPaymentMethodsSection() != null
+                        && !mPaymentUIsManager.getPaymentMethodsSection().isEmpty());
 
-        if (!mCanMakePayment || (!havePaymentApps && !mMerchantSupportsAutofillCards)) {
+        if (!mCanMakePayment
+                || (!havePaymentApps && !mPaymentUIsManager.merchantSupportsAutofillCards())) {
             // All factories have responded, but none of them have apps. It's possible to add credit
             // cards, but the merchant does not support them either. The payment request must be
             // rejected.
@@ -2847,7 +2887,8 @@
         }
 
         // If the payment method was an Autofill credit card with an identifier, record its use.
-        PaymentApp selectedPaymentMethod = (PaymentApp) mPaymentMethodsSection.getSelectedItem();
+        PaymentApp selectedPaymentMethod =
+                (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem();
         if (selectedPaymentMethod != null
                 && selectedPaymentMethod.getPaymentAppType() == PaymentAppType.AUTOFILL
                 && !selectedPaymentMethod.getIdentifier().isEmpty()) {
@@ -2907,10 +2948,11 @@
     public void onFocusChanged(@PaymentRequestUI.DataType int dataType, boolean willFocus) {
         assert dataType == PaymentRequestUI.DataType.SHIPPING_ADDRESSES;
 
-        if (mShippingAddressesSection.getSelectedItem() == null) return;
+        if (mPaymentUIsManager.getShippingAddressesSection().getSelectedItem() == null) return;
 
         AutofillAddress selectedAddress =
-                (AutofillAddress) mShippingAddressesSection.getSelectedItem();
+                (AutofillAddress) mPaymentUIsManager.getShippingAddressesSection()
+                        .getSelectedItem();
 
         // The label should only include the country if the view is focused.
         if (willFocus) {
@@ -2920,7 +2962,8 @@
         }
 
         mPaymentUIsManager.getPaymentRequestUI().updateSection(
-                PaymentRequestUI.DataType.SHIPPING_ADDRESSES, mShippingAddressesSection);
+                PaymentRequestUI.DataType.SHIPPING_ADDRESSES,
+                mPaymentUIsManager.getShippingAddressesSection());
     }
 
     @Override
@@ -2999,12 +3042,12 @@
         setShowingPaymentRequest(null);
         mIsCurrentPaymentRequestShowing = false;
 
-        if (mPaymentMethodsSection != null) {
-            for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) {
-                EditableOption option = mPaymentMethodsSection.getItem(i);
+        if (mPaymentUIsManager.getPaymentMethodsSection() != null) {
+            for (int i = 0; i < mPaymentUIsManager.getPaymentMethodsSection().getSize(); i++) {
+                EditableOption option = mPaymentUIsManager.getPaymentMethodsSection().getItem(i);
                 ((PaymentApp) option).dismissInstrument();
             }
-            mPaymentMethodsSection = null;
+            mPaymentUIsManager.setPaymentMethodsSection(null);
         }
 
         if (mObservedTabModelSelector != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java
index 1918f50..72535575 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.payments.ui;
 
+import org.chromium.chrome.browser.payments.AddressEditor;
+import org.chromium.chrome.browser.payments.AutofillPaymentAppCreator;
+import org.chromium.chrome.browser.payments.CardEditor;
 import org.chromium.chrome.browser.payments.PaymentRequestImpl;
 
 /**
@@ -14,6 +17,17 @@
     private PaymentRequestUI mPaymentRequestUI;
     private PaymentUisShowStateReconciler mPaymentUisShowStateReconciler;
 
+    private final AddressEditor mAddressEditor;
+    private final CardEditor mCardEditor;
+
+    private boolean mMerchantSupportsAutofillCards;
+    private SectionInformation mPaymentMethodsSection;
+    private SectionInformation mShippingAddressesSection;
+    private ContactDetailsSection mContactSection;
+    private AutofillPaymentAppCreator mAutofillPaymentAppCreator;
+
+    private boolean mCanUserAddCreditCard;
+
     /**
      * This class is to coordinate the show state of a bottom sheet UI (either expandable payment
      * handler or minimal UI) and the Payment Request UI so that these visibility rules are
@@ -68,8 +82,14 @@
         }
     }
 
-    /** Create PaymentUIsManager. */
-    public PaymentUIsManager() {
+    /**
+     * Create PaymentUIsManager.
+     * @param addressEditor The AddressEditor of the PaymentRequest UI.
+     * @param cardEditor The CardEditor of the PaymentRequest UI.
+     */
+    public PaymentUIsManager(AddressEditor addressEditor, CardEditor cardEditor) {
+        mAddressEditor = addressEditor;
+        mCardEditor = cardEditor;
         mPaymentUisShowStateReconciler = new PaymentUisShowStateReconciler();
     }
 
@@ -90,4 +110,74 @@
     public PaymentUisShowStateReconciler getPaymentUisShowStateReconciler() {
         return mPaymentUisShowStateReconciler;
     }
+
+    /** @return Get the AddressEditor of the PaymentRequest UI. */
+    public AddressEditor getAddressEditor() {
+        return mAddressEditor;
+    }
+
+    /** @return Get the CardEditor of the PaymentRequest UI. */
+    public CardEditor getCardEditor() {
+        return mCardEditor;
+    }
+
+    /** @return Whether the merchant supports autofill cards. */
+    public boolean merchantSupportsAutofillCards() {
+        return mMerchantSupportsAutofillCards;
+    }
+
+    /** Set whether the merchant supports autofill cards. */
+    public void setMerchantSupportsAutofillCards(boolean merchantSupportsAutofillCards) {
+        mMerchantSupportsAutofillCards = merchantSupportsAutofillCards;
+    }
+
+    /** @return Get the PaymentMethodsSection of the PaymentRequest UI. */
+    public SectionInformation getPaymentMethodsSection() {
+        return mPaymentMethodsSection;
+    }
+
+    /** Set the PaymentMethodsSection of the PaymentRequest UI. */
+    public void setPaymentMethodsSection(SectionInformation paymentMethodsSection) {
+        mPaymentMethodsSection = paymentMethodsSection;
+    }
+
+    /** Get the ShippingAddressesSection of the PaymentRequest UI. */
+    public SectionInformation getShippingAddressesSection() {
+        return mShippingAddressesSection;
+    }
+
+    /** Set the ShippingAddressesSection of the PaymentRequest UI. */
+    public void setShippingAddressesSection(SectionInformation shippingAddressesSection) {
+        mShippingAddressesSection = shippingAddressesSection;
+    }
+
+    /** Get the ContactSection of the PaymentRequest UI. */
+    public ContactDetailsSection getContactSection() {
+        return mContactSection;
+    }
+
+    /** Set the ContactSection of the PaymentRequest UI. */
+    public void setContactSection(ContactDetailsSection contactSection) {
+        mContactSection = contactSection;
+    }
+
+    /** Get the AutofillPaymentAppCreator. */
+    public AutofillPaymentAppCreator getAutofillPaymentAppCreator() {
+        return mAutofillPaymentAppCreator;
+    }
+
+    /** Set the AutofillPaymentAppCreator. */
+    public void setAutofillPaymentAppCreator(AutofillPaymentAppCreator autofillPaymentAppCreator) {
+        mAutofillPaymentAppCreator = autofillPaymentAppCreator;
+    }
+
+    /** @return Whether user can add credit card. */
+    public boolean canUserAddCreditCard() {
+        return mCanUserAddCreditCard;
+    }
+
+    /** Set whether user can add credit card. */
+    public void setCanUserAddCreditCard(boolean canUserAddCreditCard) {
+        mCanUserAddCreditCard = canUserAddCreditCard;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java
index 55caf26..5b34a123 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java
@@ -95,7 +95,7 @@
 
     private void update() {
         ViewState viewState;
-        if (!AndroidSyncSettings.get().isMasterSyncEnabled()) {
+        if (!AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync()) {
             viewState = getStateForEnableAndroidSync();
         } else if (!AndroidSyncSettings.get().isChromeSyncEnabled()) {
             viewState = getStateForEnableChromeSync();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
index 8f4b1daa..ac18730 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
@@ -14,6 +14,7 @@
 import org.chromium.chrome.browser.signin.ProfileDataCache;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.components.signin.AccountUtils;
 import org.chromium.components.signin.AccountsChangeObserver;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -94,15 +95,23 @@
             mModel.set(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED, false);
             mSelectedAccountName = null;
             mModel.set(AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA, null);
-        } else {
-            // TODO(https://crbug.com/1096977): Test and handle the scenario when
-            // the existing account list changes to a different list, we need to
-            // separate the two cases when the current selected account name is in the
-            // new list and not in the new list.
+        } else if (!mModel.get(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED)
+                && !isSelectedAccountInAccountList(accounts)) {
+            // The selected account is _only_ updated when the account list is collapsed and
+            // the current selected account name is not in the new account list
+            // (or there is no selected account).
             setSelectedAccountName(accounts.get(0).name);
         }
     }
 
+    /**
+     * Returns true if there is selected account and it is in the account list.
+     */
+    private boolean isSelectedAccountInAccountList(List<Account> accounts) {
+        return mSelectedAccountName != null
+                && AccountUtils.findAccountByName(accounts, mSelectedAccountName) != null;
+    }
+
     private void setSelectedAccountName(String accountName) {
         mSelectedAccountName = accountName;
         mProfileDataCache.update(Collections.singletonList(mSelectedAccountName));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
index e92fe96..c50509d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
@@ -18,12 +18,18 @@
             view.getSelectedAccountView().setOnClickListener(v -> {
                 model.get(AccountPickerBottomSheetProperties.ON_SELECTED_ACCOUNT_CLICKED).run();
             });
-        } else if (propertyKey == AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED
-                && model.get(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED)) {
-            view.expandAccountList();
+        } else if (propertyKey == AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED) {
+            if (model.get(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED)) {
+                view.expandAccountList();
+            } else {
+                boolean isSelectedAccountNonNull =
+                        model.get(AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA) != null;
+                view.collapseAccountList(isSelectedAccountNonNull);
+            }
         } else if (propertyKey == AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA
                 && !model.get(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED)) {
-            // Selected account data is only updated when the account list is collapsed.
+            // Selected account data (which can be null) is only updated
+            // when the account list is collapsed.
             DisplayableProfileData profileData =
                     model.get(AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA);
             view.collapseAccountList(profileData != null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java
index 77a0322..2702c5d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java
@@ -20,6 +20,7 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.components.sync.SyncContentResolverDelegate;
@@ -120,11 +121,11 @@
      * @return true if sync is on, false otherwise
      */
     public boolean isSyncEnabled() {
-        return mMasterSyncEnabled && mChromeSyncEnabled;
+        return mChromeSyncEnabled && doesMasterSyncSettingAllowChromeSync();
     }
 
     /**
-     * Checks whether sync is currently enabled from Chrome for a given account.
+     * Checks whether sync is currently enabled for Chrome for a given account.
      *
      * It checks only Chrome sync setting for the given account,
      * and ignores the master sync setting.
@@ -137,10 +138,13 @@
     }
 
     /**
-     * Checks whether the master sync flag for Android is currently enabled.
+     * Checks whether the master sync flag for Android allows syncing Chrome
+     * data.
      */
-    public boolean isMasterSyncEnabled() {
-        return mMasterSyncEnabled;
+    public boolean doesMasterSyncSettingAllowChromeSync() {
+        return mMasterSyncEnabled
+                || ChromeFeatureList.isEnabled(
+                        ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
index ba06e42..e4b8f0a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
@@ -114,7 +114,7 @@
         // TODO(crbug.com/921025): Don't mix these two concepts.
 
         mProfileSyncService.setSyncAllowedByPlatform(
-                AndroidSyncSettings.get().isMasterSyncEnabled());
+                AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync());
 
         boolean isSyncEnabled = AndroidSyncSettings.get().isSyncEnabled();
         if (isSyncEnabled == mProfileSyncService.isSyncRequested()) return;
@@ -127,7 +127,7 @@
                 // prefs (here and in the Sync customization UI).
                 AndroidSyncSettings.get().enableChromeSync();
             } else {
-                if (AndroidSyncSettings.get().isMasterSyncEnabled()) {
+                if (AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync()) {
                     RecordHistogram.recordEnumeratedHistogram("Sync.StopSource",
                             StopSource.ANDROID_CHROME_SYNC, StopSource.STOP_SOURCE_LIMIT);
                 } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java
index 0f537d7..fa8b0f1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java
@@ -72,7 +72,7 @@
      */
     @SyncError
     public static int getSyncError() {
-        if (!AndroidSyncSettings.get().isMasterSyncEnabled()) {
+        if (!AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync()) {
             return SyncError.ANDROID_SYNC_DISABLED;
         }
 
@@ -159,7 +159,7 @@
         ProfileSyncService profileSyncService = ProfileSyncService.get();
         Resources res = context.getResources();
 
-        if (!AndroidSyncSettings.get().isMasterSyncEnabled()) {
+        if (!AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync()) {
             return res.getString(R.string.sync_android_master_sync_disabled);
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/language/LanguageSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/language/settings/LanguageSettingsTest.java
similarity index 89%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/settings/language/LanguageSettingsTest.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/language/settings/LanguageSettingsTest.java
index 02378790..9e37950 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/language/LanguageSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/language/settings/LanguageSettingsTest.java
@@ -2,7 +2,7 @@
 // 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.settings.language;
+package org.chromium.chrome.browser.language.settings;
 
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
@@ -33,11 +33,7 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.language.settings.LanguageItem;
-import org.chromium.chrome.browser.language.settings.LanguageListBaseAdapter;
-import org.chromium.chrome.browser.language.settings.LanguageSettings;
 import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
 import org.chromium.chrome.browser.translate.TranslateBridge;
@@ -148,8 +144,8 @@
         onView(allOf(hasSibling(withText(R.string.languages_item_option_offer_to_translate)),
                        withId(R.id.menu_item_end_icon)))
                 .check((v, e) -> {
-                    Assert.assertNotNull(
-                            "There should exist an icon next to the text to indicate 'offer to translate' is on",
+                    Assert.assertNotNull("There should exist an icon next to the text to indicate "
+                                    + "'offer to translate' is on",
                             ((ImageView) v).getDrawable());
                 });
 
@@ -187,9 +183,9 @@
         boolean enabledInDefault = pref.isChecked();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             boolean enabled =
-                    PrefServiceBridge.getInstance().getBoolean(Pref.OFFER_TRANSLATE_ENABLED);
-            Assert.assertEquals(
-                    "The state of switch widget is different from local preference of 'offer to translate'.",
+                    LanguageSettings.getPrefService().getBoolean(Pref.OFFER_TRANSLATE_ENABLED);
+            Assert.assertEquals("The state of switch widget is different from local preference of "
+                            + "'offer to translate'.",
                     enabledInDefault, enabled);
         });
 
@@ -204,10 +200,10 @@
         // Toggle the switch.
         onView(withId(R.id.switchWidget)).perform(click());
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals(
-                    "Preference of 'offer to translate' should be toggled when switch widget is clicked.",
+            Assert.assertEquals("Preference of 'offer to translate' should be toggled when switch "
+                            + "widget is clicked.",
                     !enabledInDefault,
-                    PrefServiceBridge.getInstance().getBoolean(Pref.OFFER_TRANSLATE_ENABLED));
+                    LanguageSettings.getPrefService().getBoolean(Pref.OFFER_TRANSLATE_ENABLED));
         });
 
         TestThreadUtils.runOnUiThreadBlocking((Runnable) moreButton::performClick);
@@ -217,7 +213,7 @@
 
         // Reset state.
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            PrefServiceBridge.getInstance().setBoolean(
+            LanguageSettings.getPrefService().setBoolean(
                     Pref.OFFER_TRANSLATE_ENABLED, enabledInDefault);
         });
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
index 7ade8c9..7a2ac63 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
@@ -38,7 +38,6 @@
 import org.chromium.chrome.browser.engagement.SiteEngagementService;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -49,6 +48,7 @@
 import org.chromium.components.permissions.PermissionDialogController;
 import org.chromium.components.url_formatter.SchemeDisplay;
 import org.chromium.components.url_formatter.UrlFormatter;
+import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -444,8 +444,8 @@
         // Disable notification vibration in preferences.
         TestThreadUtils.runOnUiThreadBlocking(
                 ()
-                        -> PrefServiceBridge.getInstance().setBoolean(
-                                NOTIFICATIONS_VIBRATE_ENABLED, false));
+                        -> UserPrefs.get(Profile.getLastUsedRegularProfile())
+                                   .setBoolean(NOTIFICATIONS_VIBRATE_ENABLED, false));
 
         Notification notification = showAndGetNotification("MyNotification", notificationOptions);
 
@@ -494,8 +494,8 @@
         // By default, vibration is enabled in notifications.
         TestThreadUtils.runOnUiThreadBlocking(
                 ()
-                        -> Assert.assertTrue(PrefServiceBridge.getInstance().getBoolean(
-                                NOTIFICATIONS_VIBRATE_ENABLED)));
+                        -> Assert.assertTrue(UserPrefs.get(Profile.getLastUsedRegularProfile())
+                                                     .getBoolean(NOTIFICATIONS_VIBRATE_ENABLED)));
 
         Notification notification = showAndGetNotification("MyNotification", "{ vibrate: 42 }");
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
index cde42a6..6f68842 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
@@ -57,8 +57,8 @@
 import org.chromium.chrome.browser.partnercustomizations.BasePartnerBrowserCustomizationIntegrationTestRule;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.HomeButton;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
@@ -75,6 +75,7 @@
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.FeatureConstants;
 import org.chromium.components.feature_engagement.Tracker;
+import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -293,7 +294,8 @@
     public void testToggleFeed_WithHomepage() {
         // Test to toggle NTP when feed is hidden.
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            PrefServiceBridge.getInstance().setBoolean(Pref.ARTICLES_LIST_VISIBLE, false);
+            UserPrefs.get(Profile.getLastUsedRegularProfile())
+                    .setBoolean(Pref.ARTICLES_LIST_VISIBLE, false);
         });
         launchNewTabPage();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
index cdd39f35..2003711 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
@@ -40,7 +40,6 @@
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
@@ -553,7 +552,6 @@
 
     @Test
     @SmallTest
-    @DisabledTest(message = "Flaky - https://crbug.com/1100967")
     @Features.
     EnableFeatures({ChromeFeatureList.OMNIBOX_ENABLE_CLIPBOARD_PROVIDER_IMAGE_SUGGESTIONS})
     public void testImageSearch() throws InterruptedException, Exception {
@@ -634,7 +632,6 @@
 
     @Test
     @SmallTest
-    @DisabledTest(message = "Flaky - https://crbug.com/1100967")
     @Features.
     EnableFeatures({ChromeFeatureList.OMNIBOX_ENABLE_CLIPBOARD_PROVIDER_IMAGE_SUGGESTIONS})
     public void testImageSearch_OnlyTrustedIntentCanPost() throws InterruptedException, Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java
index 1187d1d..6ec9f0b5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java
@@ -19,8 +19,9 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.policy.test.annotations.Policies;
@@ -42,8 +43,8 @@
                 () -> { ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); });
 
         CriteriaHelper.pollUiThread(() -> {
-            return PrefServiceBridge.getInstance().isManagedPreference(
-                    Pref.CREDENTIALS_ENABLE_SERVICE);
+            return UserPrefs.get(Profile.getLastUsedRegularProfile())
+                    .isManagedPreference(Pref.CREDENTIALS_ENABLE_SERVICE);
         });
 
         mSettingsActivityTestRule.startSettingsActivity();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
index 9515316..6a01200 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -65,10 +65,14 @@
         }
     }
 
-    private static final String FULL_NAME1 = "Test Account1";
-    private static final String GIVEN_NAME1 = "Account1";
-    private static final String ACCOUNT_NAME1 = "test.account1@gmail.com";
-    private static final String ACCOUNT_NAME2 = "test.account2@gmail.com";
+    private static final ProfileDataSource.ProfileData PROFILE_DATA1 =
+            new ProfileDataSource.ProfileData(
+                    /* accountName= */ "test.account1@gmail.com", /* avatar= */ null,
+                    /* fullName= */ "Test Account1", /* givenName= */ "Account1");
+    private static final ProfileDataSource.ProfileData PROFILE_DATA2 =
+            new ProfileDataSource.ProfileData(
+                    /* accountName= */ "test.account2@gmail.com", /* avatar= */ null,
+                    /* fullName= */ null, /* givenName= */ null);
 
     @Rule
     public final Features.InstrumentationProcessor mProcessor =
@@ -95,46 +99,27 @@
     @Before
     public void setUp() {
         initMocks(this);
-        addAccount(ACCOUNT_NAME1, FULL_NAME1, GIVEN_NAME1);
-        addAccount(ACCOUNT_NAME2, null, null);
+        mAccountManagerTestRule.addAccount(PROFILE_DATA1.getAccountName(), PROFILE_DATA1);
+        mAccountManagerTestRule.addAccount(PROFILE_DATA2.getAccountName(), PROFILE_DATA2);
         mActivityTestRule.startMainActivityOnBlankPage();
     }
 
-    private void buildAndShowAccountPickerBottomSheet() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            AccountPickerBottomSheetCoordinator accountPickerBottomSheetCoordinator =
-                    new AccountPickerBottomSheetCoordinator(mActivityTestRule.getActivity(),
-                            getBottomSheetController(), mAccountPickerDelegateMock);
-        });
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-    }
-
     @Test
     @MediumTest
     public void testCollapsedSheetWithAccount() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(R.string.signin_account_picker_dialog_title)).check(matches(isDisplayed()));
-        onView(withText(ACCOUNT_NAME1)).check(matches(isDisplayed()));
-        onView(withText(FULL_NAME1)).check(matches(isDisplayed()));
-        onView(withId(R.id.account_selection_mark)).check(matches(isDisplayed()));
-        String continueAsText = mActivityTestRule.getActivity().getString(
-                R.string.signin_promo_continue_as, GIVEN_NAME1);
-        onView(withText(continueAsText)).check(matches(isDisplayed()));
-        onView(withText(ACCOUNT_NAME2)).check(doesNotExist());
-        onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
+        buildAndShowCollapsedBottomSheet();
+        checkCollapsedAccountList(PROFILE_DATA1);
     }
 
     @Test
     @MediumTest
     public void testExpandedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
-        // Check expanded bottom sheet
-        onView(allOf(withText(ACCOUNT_NAME1), withEffectiveVisibility(VISIBLE)))
+        buildAndShowExpandedBottomSheet();
+        onView(allOf(withText(PROFILE_DATA1.getAccountName()), withEffectiveVisibility(VISIBLE)))
                 .check(matches(isDisplayed()));
-        onView(allOf(withText(FULL_NAME1), withEffectiveVisibility(VISIBLE)))
+        onView(allOf(withText(PROFILE_DATA1.getFullName()), withEffectiveVisibility(VISIBLE)))
                 .check(matches(isDisplayed()));
-        onView(withText(ACCOUNT_NAME2)).check(matches(isDisplayed()));
+        onView(withText(PROFILE_DATA2.getAccountName())).check(matches(isDisplayed()));
         onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed()));
 
         onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed())));
@@ -150,15 +135,15 @@
         // torn down in the end of the test in AccountManagerTestRule.
         AccountManagerFacadeProvider.setInstanceForTests(
                 new FakeAccountManagerFacade(mFakeProfileDataSource));
-        buildAndShowAccountPickerBottomSheet();
+        buildAndShowCollapsedBottomSheet();
         checkZeroAccountBottomSheet();
     }
 
     @Test
     @MediumTest
     public void testDismissCollapsedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(ACCOUNT_NAME1)).check(matches(isDisplayed()));
+        buildAndShowCollapsedBottomSheet();
+        onView(withText(PROFILE_DATA1.getAccountName())).check(matches(isDisplayed()));
         BottomSheetController controller = getBottomSheetController();
         Assert.assertTrue(controller.isSheetOpen());
         Assert.assertEquals(2, mFakeProfileDataSource.getNumberOfObservers());
@@ -170,8 +155,7 @@
     @Test
     @MediumTest
     public void testDismissExpandedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
+        buildAndShowExpandedBottomSheet();
         BottomSheetController controller = getBottomSheetController();
         Assert.assertTrue(controller.isSheetOpen());
         Assert.assertEquals(2, mFakeProfileDataSource.getNumberOfObservers());
@@ -183,9 +167,9 @@
     @Test
     @MediumTest
     public void testAccountDisappearedInCollapsedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        mAccountManagerTestRule.removeAccountAndWaitForSeeding(ACCOUNT_NAME1);
-        mAccountManagerTestRule.removeAccountAndWaitForSeeding(ACCOUNT_NAME2);
+        buildAndShowCollapsedBottomSheet();
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA1.getAccountName());
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA2.getAccountName());
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
         checkZeroAccountBottomSheet();
     }
@@ -193,10 +177,9 @@
     @Test
     @MediumTest
     public void testAccountDisappearedInExpandedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
-        mAccountManagerTestRule.removeAccountAndWaitForSeeding(ACCOUNT_NAME1);
-        mAccountManagerTestRule.removeAccountAndWaitForSeeding(ACCOUNT_NAME2);
+        buildAndShowExpandedBottomSheet();
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA1.getAccountName());
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA2.getAccountName());
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
         checkZeroAccountBottomSheet();
     }
@@ -204,31 +187,45 @@
     @Test
     @MediumTest
     public void testAccountReappearedInCollapsedSheet() {
-        mAccountManagerTestRule.removeAccountAndWaitForSeeding(ACCOUNT_NAME1);
-        mAccountManagerTestRule.removeAccountAndWaitForSeeding(ACCOUNT_NAME2);
-        buildAndShowAccountPickerBottomSheet();
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA1.getAccountName());
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA2.getAccountName());
+        buildAndShowCollapsedBottomSheet();
         checkZeroAccountBottomSheet();
 
-        mAccountManagerTestRule.addAccount(ACCOUNT_NAME1);
+        mAccountManagerTestRule.addAccount(PROFILE_DATA1.getAccountName());
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        onView(withText(ACCOUNT_NAME1)).check(matches(isDisplayed()));
-        onView(withText(FULL_NAME1)).check(matches(isDisplayed()));
-        String continueAsText = mActivityTestRule.getActivity().getString(
-                R.string.signin_promo_continue_as, GIVEN_NAME1);
-        onView(withText(continueAsText)).check(matches(isDisplayed()));
+        checkCollapsedAccountList(PROFILE_DATA1);
+    }
+
+    @Test
+    @MediumTest
+    public void testOtherAccountsChangeInCollapsedSheet() {
+        buildAndShowCollapsedBottomSheet();
+        checkCollapsedAccountList(PROFILE_DATA1);
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA2.getAccountName());
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        checkCollapsedAccountList(PROFILE_DATA1);
+    }
+
+    @Test
+    @MediumTest
+    public void testSelectedAccountChangeInCollapsedSheet() {
+        buildAndShowCollapsedBottomSheet();
+        mAccountManagerTestRule.removeAccountAndWaitForSeeding(PROFILE_DATA1.getAccountName());
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        checkCollapsedAccountList(PROFILE_DATA2);
     }
 
     @Test
     @MediumTest
     public void testProfileDataUpdateInExpandedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
+        buildAndShowExpandedBottomSheet();
         String newFullName = "New Full Name1";
         String newGivenName = "New Given Name1";
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mFakeProfileDataSource.setProfileData(ACCOUNT_NAME1,
+            mFakeProfileDataSource.setProfileData(PROFILE_DATA1.getAccountName(),
                     new ProfileDataSource.ProfileData(
-                            ACCOUNT_NAME1, null, newFullName, newGivenName));
+                            PROFILE_DATA1.getAccountName(), null, newFullName, newGivenName));
         });
         onView(allOf(withText(newFullName), withEffectiveVisibility(VISIBLE)))
                 .check(matches(isDisplayed()));
@@ -241,30 +238,28 @@
     @Test
     @MediumTest
     public void testSignInDefaultAccountOnCollapsedSheet() {
-        buildAndShowAccountPickerBottomSheet();
+        buildAndShowCollapsedBottomSheet();
         String continueAsText = mActivityTestRule.getActivity().getString(
-                R.string.signin_promo_continue_as, GIVEN_NAME1);
+                R.string.signin_promo_continue_as, PROFILE_DATA1.getGivenName());
         onView(withText(continueAsText)).perform(click());
-        verify(mAccountPickerDelegateMock).signIn(ACCOUNT_NAME1);
+        verify(mAccountPickerDelegateMock).signIn(PROFILE_DATA1.getAccountName());
     }
 
     @Test
     @MediumTest
     public void testSignInAnotherAccount() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
-        onView(withText(ACCOUNT_NAME2)).perform(click());
+        buildAndShowExpandedBottomSheet();
+        onView(withText(PROFILE_DATA2.getAccountName())).perform(click());
         String continueAsText = mActivityTestRule.getActivity().getString(
-                R.string.signin_promo_continue_as, ACCOUNT_NAME2);
+                R.string.signin_promo_continue_as, PROFILE_DATA2.getAccountName());
         onView(withText(continueAsText)).perform(click());
-        verify(mAccountPickerDelegateMock).signIn(ACCOUNT_NAME2);
+        verify(mAccountPickerDelegateMock).signIn(PROFILE_DATA2.getAccountName());
     }
 
     @Test
     @MediumTest
     public void testAddAccountOnExpandedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
+        buildAndShowExpandedBottomSheet();
         onView(withText(R.string.signin_add_account_to_device)).perform(click());
         verify(mAccountPickerDelegateMock).addAccount();
     }
@@ -272,32 +267,24 @@
     @Test
     @MediumTest
     public void testSelectAnotherAccountOnExpandedSheet() {
-        buildAndShowAccountPickerBottomSheet();
-        onView(withText(FULL_NAME1)).perform(click());
-        onView(withText(ACCOUNT_NAME2)).perform(click());
-
-        onView(allOf(withText(ACCOUNT_NAME2), withEffectiveVisibility(VISIBLE)))
-                .check(matches(isDisplayed()));
-        String continueAsText = mActivityTestRule.getActivity().getString(
-                R.string.signin_promo_continue_as, ACCOUNT_NAME2);
-        onView(withText(continueAsText)).check(matches(isDisplayed()));
-
-        onView(allOf(withText(ACCOUNT_NAME1), withEffectiveVisibility(VISIBLE)))
-                .check(doesNotExist());
-        onView(allOf(withText(FULL_NAME1), withEffectiveVisibility(VISIBLE))).check(doesNotExist());
-        onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
+        buildAndShowExpandedBottomSheet();
+        onView(withText(PROFILE_DATA2.getAccountName())).perform(click());
+        checkCollapsedAccountList(PROFILE_DATA2);
     }
 
-    private void addAccount(String accountName, String fullName, String givenName) {
-        ProfileDataSource.ProfileData profileData =
-                new ProfileDataSource.ProfileData(accountName, null, fullName, givenName);
-        mAccountManagerTestRule.addAccount(accountName, profileData);
+    @Test
+    @MediumTest
+    public void testSelectTheSameAccountOnExpandedSheet() {
+        buildAndShowExpandedBottomSheet();
+        onView(allOf(withText(PROFILE_DATA1.getAccountName()), withEffectiveVisibility(VISIBLE)))
+                .perform(click());
+        checkCollapsedAccountList(PROFILE_DATA1);
     }
 
     private void checkZeroAccountBottomSheet() {
-        onView(allOf(withText(ACCOUNT_NAME1), withEffectiveVisibility(VISIBLE)))
+        onView(allOf(withText(PROFILE_DATA1.getAccountName()), withEffectiveVisibility(VISIBLE)))
                 .check(doesNotExist());
-        onView(allOf(withText(ACCOUNT_NAME2), withEffectiveVisibility(VISIBLE)))
+        onView(allOf(withText(PROFILE_DATA2.getAccountName()), withEffectiveVisibility(VISIBLE)))
                 .check(doesNotExist());
         onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
         onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed())));
@@ -307,6 +294,38 @@
         verify(mAccountPickerDelegateMock).addAccount();
     }
 
+    private void checkCollapsedAccountList(ProfileDataSource.ProfileData profileData) {
+        onView(withText(R.string.signin_account_picker_dialog_title)).check(matches(isDisplayed()));
+        onView(allOf(withText(profileData.getAccountName()), withEffectiveVisibility(VISIBLE)))
+                .check(matches(isDisplayed()));
+        if (profileData.getFullName() != null) {
+            onView(allOf(withText(profileData.getFullName()), withEffectiveVisibility(VISIBLE)))
+                    .check(matches(isDisplayed()));
+        }
+        onView(allOf(withId(R.id.account_selection_mark), withEffectiveVisibility(VISIBLE)))
+                .check(matches(isDisplayed()));
+        String continueAsText =
+                mActivityTestRule.getActivity().getString(R.string.signin_promo_continue_as,
+                        profileData.getGivenName() != null ? profileData.getGivenName()
+                                                           : profileData.getAccountName());
+        onView(withText(continueAsText)).check(matches(isDisplayed()));
+        onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
+    }
+
+    private void buildAndShowCollapsedBottomSheet() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            AccountPickerBottomSheetCoordinator accountPickerBottomSheetCoordinator =
+                    new AccountPickerBottomSheetCoordinator(mActivityTestRule.getActivity(),
+                            getBottomSheetController(), mAccountPickerDelegateMock);
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    private void buildAndShowExpandedBottomSheet() {
+        buildAndShowCollapsedBottomSheet();
+        onView(withText(PROFILE_DATA1.getFullName())).perform(click());
+    }
+
     private BottomSheetController getBottomSheetController() {
         return mActivityTestRule.getActivity()
                 .getRootUiCoordinatorForTesting()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java
index 3f9373c..5902b98 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java
@@ -182,6 +182,12 @@
 
         // The status indicator will be immediately visible.
         onView(withId(R.id.status_indicator)).check(matches(withEffectiveVisibility(VISIBLE)));
+
+        CriteriaHelper.pollUiThread(() -> {
+            Criteria.checkThat(mBrowserControlsStateProvider.getTopControlsMinHeightOffset(),
+                    Matchers.is(mStatusIndicatorContainer.getHeight()));
+        });
+
         onView(withId(R.id.control_container))
                 .check(matches(withTopMargin(mStatusIndicatorContainer.getHeight())));
         onView(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view))
@@ -202,6 +208,11 @@
 
         TestThreadUtils.runOnUiThreadBlocking(() -> mStatusIndicatorCoordinator.hide());
 
+        CriteriaHelper.pollUiThread(() -> {
+            Criteria.checkThat(
+                    mBrowserControlsStateProvider.getTopControlsMinHeightOffset(), Matchers.is(0));
+        });
+
         onView(withId(R.id.status_indicator)).check(matches(withEffectiveVisibility(GONE)));
         onView(withId(R.id.control_container)).check(matches(withTopMargin(0)));
         onView(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view))
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AndroidSyncSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AndroidSyncSettingsTest.java
index 1f06333..cbbf3d6b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AndroidSyncSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AndroidSyncSettingsTest.java
@@ -13,7 +13,9 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.Callback;
@@ -21,7 +23,11 @@
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.sync.AndroidSyncSettings.AndroidSyncSettingsObserver;
+import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.chrome.test.util.browser.Features.JUnitProcessor;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
 import org.chromium.components.signin.ChromeSigninController;
@@ -36,6 +42,7 @@
  * Tests for AndroidSyncSettings.
  */
 @RunWith(BaseJUnit4ClassRunner.class)
+@DisableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
 public class AndroidSyncSettingsTest {
     private static class CountingMockSyncContentResolverDelegate
             extends MockSyncContentResolverDelegate {
@@ -100,6 +107,9 @@
         }
     }
 
+    @Rule
+    public TestRule mProcessorRule = new JUnitProcessor();
+
     private AndroidSyncSettings mAndroidSyncSettings;
     private CountingMockSyncContentResolverDelegate mSyncContentResolverDelegate;
     private String mAuthority;
@@ -207,12 +217,13 @@
     public void testToggleMasterSyncFromSettings() throws InterruptedException {
         mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
         mSyncContentResolverDelegate.waitForLastNotificationCompleted();
-        Assert.assertTrue("master sync should be set", mAndroidSyncSettings.isMasterSyncEnabled());
+        Assert.assertTrue("master sync should be set",
+                mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync());
 
         mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
         mSyncContentResolverDelegate.waitForLastNotificationCompleted();
-        Assert.assertFalse(
-                "master sync should be unset", mAndroidSyncSettings.isMasterSyncEnabled());
+        Assert.assertFalse("master sync should be unset",
+                mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync());
     }
 
     @Test
@@ -251,8 +262,8 @@
         mSyncContentResolverDelegate.waitForLastNotificationCompleted();
         Assert.assertFalse(
                 "sync should be disabled due to master sync", mAndroidSyncSettings.isSyncEnabled());
-        Assert.assertFalse(
-                "master sync should be disabled", mAndroidSyncSettings.isMasterSyncEnabled());
+        Assert.assertFalse("master sync should be disabled",
+                mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync());
         Assert.assertTrue(
                 "sync should be set for chrome app", mAndroidSyncSettings.isChromeSyncEnabled());
     }
@@ -324,7 +335,7 @@
                 mSyncContentResolverDelegate.mGetSyncAutomaticallyCalls.get();
 
         // Do a bunch of reads.
-        mAndroidSyncSettings.isMasterSyncEnabled();
+        mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync();
         mAndroidSyncSettings.isSyncEnabled();
         mAndroidSyncSettings.isChromeSyncEnabled();
 
@@ -338,7 +349,7 @@
 
         // Do a bunch of reads for alternate account.
         updateAccount(mAlternateAccount);
-        mAndroidSyncSettings.isMasterSyncEnabled();
+        mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync();
         mAndroidSyncSettings.isSyncEnabled();
         mAndroidSyncSettings.isChromeSyncEnabled();
 
@@ -441,4 +452,23 @@
         // Should still be enabled.
         Assert.assertTrue(mSyncContentResolverDelegate.getSyncAutomatically(mAccount, mAuthority));
     }
+
+    @Test
+    @SmallTest
+    @Feature({"Sync"})
+    @EnableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
+    public void testSyncStateDoesNotDependOnMasterSync() throws InterruptedException {
+        mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
+        mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
+        mSyncContentResolverDelegate.waitForLastNotificationCompleted();
+        Assert.assertTrue(mAndroidSyncSettings.isChromeSyncEnabled());
+        Assert.assertTrue(mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync());
+        Assert.assertTrue(mAndroidSyncSettings.isSyncEnabled());
+
+        mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, false);
+        mSyncContentResolverDelegate.waitForLastNotificationCompleted();
+        Assert.assertFalse(mAndroidSyncSettings.isChromeSyncEnabled());
+        Assert.assertTrue(mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync());
+        Assert.assertFalse(mAndroidSyncSettings.isSyncEnabled());
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
index 87582c2..7c0ff5d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
@@ -55,6 +55,7 @@
 
     @SmallTest
     @Test
+    @DisabledTest(message = "https://crbug.com/1101760")
     public void testNonEncryptedSaveRestore() throws InterruptedException {
         testSaveRestoreDelete(false);
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdaterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdaterTest.java
index 992e12d..b225066 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdaterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/permissiondelegation/LocationPermissionUpdaterTest.java
@@ -29,6 +29,7 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -47,10 +48,14 @@
     private static final Origin ORIGIN = Origin.create("https://www.website.com");
     private static final String PACKAGE_NAME = "com.package.name";
     private static final String OTHER_PACKAGE_NAME = "com.other.package.name";
+    private static final long CALLBACK = 12;
 
     @Rule
     public TestRule mProcessor = new Features.JUnitProcessor();
 
+    @Rule
+    public JniMocker mocker = new JniMocker();
+
     @Mock
     public TrustedWebActivityPermissionManager mPermissionManager;
     @Mock
@@ -58,6 +63,9 @@
     @Mock
     public TrustedWebActivityUmaRecorder mUmaRecorder;
 
+    @Mock
+    private InstalledWebappBridge.Natives mNativeMock;
+
     private LocationPermissionUpdater mLocationPermissionUpdater;
     private ShadowPackageManager mShadowPackageManager;
 
@@ -67,6 +75,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        mocker.mock(InstalledWebappBridgeJni.TEST_HOOKS, mNativeMock);
+
         PackageManager pm = RuntimeEnvironment.application.getPackageManager();
         mShadowPackageManager = shadowOf(pm);
         mLocationPermissionUpdater = new LocationPermissionUpdater(
@@ -80,7 +90,7 @@
         installTrustedWebActivityService(ORIGIN, PACKAGE_NAME);
         setLocationEnabledForClient(false);
 
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
 
         verifyPermissionUpdated(false);
     }
@@ -91,7 +101,7 @@
         installTrustedWebActivityService(ORIGIN, PACKAGE_NAME);
         setLocationEnabledForClient(true);
 
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
 
         verifyPermissionUpdated(true);
     }
@@ -101,11 +111,11 @@
     public void updatesPermission_onSubsequentCalls() {
         installTrustedWebActivityService(ORIGIN, PACKAGE_NAME);
         setLocationEnabledForClient(true);
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
         verifyPermissionUpdated(true);
 
         setLocationEnabledForClient(false);
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
         verifyPermissionUpdated(false);
     }
 
@@ -114,13 +124,13 @@
     public void updatesPermission_onNewClient() {
         installTrustedWebActivityService(ORIGIN, PACKAGE_NAME);
         setLocationEnabledForClient(true);
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
         verifyPermissionUpdated(true);
 
         installBrowsableIntentHandler(ORIGIN, OTHER_PACKAGE_NAME);
         installTrustedWebActivityService(ORIGIN, OTHER_PACKAGE_NAME);
         setLocationEnabledForClient(false);
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
         verifyPermissionUpdated(OTHER_PACKAGE_NAME, false);
     }
 
@@ -130,7 +140,7 @@
         installTrustedWebActivityService(ORIGIN, PACKAGE_NAME);
         setLocationEnabledForClient(true);
 
-        mLocationPermissionUpdater.checkPermission(ORIGIN, 0 /*callback*/);
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
 
         uninstallTrustedWebActivityService(ORIGIN);
         mLocationPermissionUpdater.onClientAppUninstalled(ORIGIN);
@@ -182,6 +192,7 @@
         verify(mPermissionManager)
                 .updatePermission(eq(ORIGIN), eq(packageName), eq(ContentSettingsType.GEOLOCATION),
                         eq(enabled));
+        verify(mNativeMock).notifyPermissionResult(eq(CALLBACK), eq(enabled));
     }
 
     private void verifyPermissionReset() {
@@ -193,4 +204,21 @@
         verify(mPermissionManager, never())
                 .resetStoredPermission(eq(ORIGIN), eq(ContentSettingsType.GEOLOCATION));
     }
+
+    @Test
+    @Feature("TrustedWebActivity")
+    public void updatesPermissionOnlyOnce_incorrectReturnsFromTwaService() {
+        doAnswer(invocation -> {
+            TrustedWebActivityClient.PermissionCheckCallback callback = invocation.getArgument(1);
+            // PermissionCheckCallback is invoked twice with different result.
+            callback.onPermissionCheck(new ComponentName(PACKAGE_NAME, "FakeClass"), false);
+            callback.onPermissionCheck(new ComponentName(PACKAGE_NAME, "FakeClass"), true);
+            return true;
+        })
+                .when(mTrustedWebActivityClient)
+                .checkLocationPermission(eq(ORIGIN), any());
+
+        mLocationPermissionUpdater.checkPermission(ORIGIN, CALLBACK);
+        verifyPermissionUpdated(PACKAGE_NAME, false);
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java
index 5196804..0da49211 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java
@@ -7,7 +7,6 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.Activity;
-import android.os.Build;
 import android.support.test.filters.SmallTest;
 import android.text.SpannableStringBuilder;
 import android.view.ViewStructure;
@@ -22,7 +21,6 @@
 import org.robolectric.Robolectric;
 
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.omnibox.UrlBar.UrlBarDelegate;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 
@@ -49,7 +47,6 @@
 
     @Test
     @SmallTest
-    @MinAndroidSdkLevel(Build.VERSION_CODES.O)
     @Feature("Omnibox")
     public void testAutofillStructureReceivesFullURL() {
         mUrlBar.setTextForAutofillServices("https://www.google.com");
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java
index 7843df0..f86a0bf 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java
@@ -17,7 +17,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.os.Build;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -33,7 +32,6 @@
 import org.chromium.base.Promise;
 import org.chromium.base.UserDataHost;
 import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.tab.TabCreationState;
 import org.chromium.chrome.browser.tab.TabHidingType;
@@ -54,7 +52,6 @@
 /** Unit tests for PageViewObserver. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
-@MinAndroidSdkLevel(Build.VERSION_CODES.P)
 public final class PageViewObserverTest {
     private static final String STARTING_URL = "http://starting.url";
     private static final String DIFFERENT_URL = "http://different.url";
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index bd35f4c..20b4261 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-86.0.4203.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-86.0.4204.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/proguard/OWNERS b/chrome/android/proguard/OWNERS
new file mode 100644
index 0000000..9c1c219
--- /dev/null
+++ b/chrome/android/proguard/OWNERS
@@ -0,0 +1,4 @@
+agrieve@chromium.org
+smaier@chromium.org
+
+# Team: build@chromium.org
diff --git a/chrome/android/java/apk_for_test.flags b/chrome/android/proguard/apk_for_test.flags
similarity index 100%
rename from chrome/android/java/apk_for_test.flags
rename to chrome/android/proguard/apk_for_test.flags
diff --git a/chrome/android/java/proguard.flags b/chrome/android/proguard/main.flags
similarity index 100%
rename from chrome/android/java/proguard.flags
rename to chrome/android/proguard/main.flags
diff --git a/chrome/android/java/static_library_dex_reference_workarounds.flags b/chrome/android/proguard/static_library_dex_reference_workarounds.flags
similarity index 100%
rename from chrome/android/java/static_library_dex_reference_workarounds.flags
rename to chrome/android/proguard/static_library_dex_reference_workarounds.flags
diff --git a/chrome/android/java/trichrome.flags b/chrome/android/proguard/trichrome.flags
similarity index 100%
rename from chrome/android/java/trichrome.flags
rename to chrome/android/proguard/trichrome.flags
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni
index 21d5a551..42b51993 100644
--- a/chrome/android/trichrome.gni
+++ b/chrome/android/trichrome.gni
@@ -185,11 +185,11 @@
       proguard_configs = [
         "//base/android/proguard/chromium_apk.flags",
         "//base/android/proguard/chromium_code.flags",
-        "//chrome/android/java/trichrome.flags",
+        "//chrome/android/proguard/trichrome.flags",
       ]
       if (trichrome_synchronized_proguard) {
         proguard_configs += [
-          "//chrome/android/java/static_library_dex_reference_workarounds.flags",
+          "//chrome/android/proguard/static_library_dex_reference_workarounds.flags",
           "//base/android/proguard/enable_obfuscation.flags",
         ]
       } else {
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn
index c3bbeec..9d7201f 100644
--- a/chrome/android/webapk/shell_apk/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -253,7 +253,7 @@
       proguard_enabled = true
       proguard_configs = [
         "//chrome/android/webapk/shell_apk/proguard.flags",
-        "//chrome/android/java/proguard.flags",
+        "//chrome/android/proguard/main.flags",
         "//base/android/proguard/chromium_apk.flags",
         "//base/android/proguard/chromium_code.flags",
       ]
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index c16ff790..71080e2 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -3450,6 +3450,9 @@
   <message name="IDS_NETWORK_UI_NETWORK_HEALTH" desc="Label for network health snapshot. 'Network Health' is a condensend summary of all networking devices on the system and their active networks">
     Network Health Snapshot
   </message>
+  <message name="IDS_NETWORK_UI_NETWORK_DIAGNOSTICS" desc="Label for network diagnostics routines">
+    Network Diagnostic Routines
+  </message>
   <message name="IDS_NETWORK_UI_NETWORK_LISTS" desc="Label for network lists section">
     Network (Service) and Device properties
   </message>
@@ -3555,6 +3558,43 @@
   <message name="IDS_NETWORK_HEALTH_STATE_ONLINE" desc="Network State - Online. This state is when a network device is connected to a network and can access the internet.">
     Online
   </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_LAN_CONNECTIVITY" desc="Label for Network diagnostics `LAN connectivity` test. This test determines if the device is connected to a Local Area Network (LAN)">
+    Lan Connectivity
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_SIGNAL_STRENGTH" desc="Label for Network diagnostics `signal strength` test. This test ensures that a WiFi signal is strong enough for a stable connection.">
+    Signal Strength
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED" desc="Label for Network diagnostics `gateway can be pinged` test. This test ensures that there is a connection to the network gateway.">
+    Gateway can be Pinged
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION" desc="Label for Network diagnostics `has secure WiFi connection` test. This test ensures that the WiFi connection is properly secure.">
+    Secure WiFi Connection
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_DNS_RESOLVER_PRESENT" desc="Label for Network diagnostics `DNS resolver present` test. This test ensures that the Domain Name Service (DNS) exists.">
+    DNS Resolver Present
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_DNS_LATENCY" desc="Label for Network diagnostics `DNS latency` test. This test makes sure the latency between the device and the Domain Name Server (DNS) is acceptable.">
+    DNS Latency
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_DNS_RESOLUTION" desc="Label for Network diagnostics `DNS resolution` test. This test ensures that the Domain Name Server (DNS) can resolve network requests.">
+    DNS Resolution
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_PASSED" desc="Label shown when a Network diagnostics routine passed">
+    Passed
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_FAILED" desc="Label shown when a Network diagnostics routine failed">
+    Failed
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_NOT_RUN" desc="Label shown when a Network diagnostics routine did not run">
+    Not Run
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_RUN" desc="Label for Network diagnostics run routine button">
+    Run
+  </message>
+  <message name="IDS_NETWORK_DIAGNOSTICS_RUN_ALL" desc="Label for Network diagnostics run all routines button">
+    Run All Routines
+  </message>
+
 
   <!-- Set time/date UI display strings -->
   <message name="IDS_SET_TIME_TITLE" desc="Title of the set time/date UI.">
@@ -5450,6 +5490,9 @@
   <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_PIN_PROMPT_INVALID_PIN" desc="Text on a pin field that tells the user the PIN is incorrect.">
+    Invalid PIN
+  </message>
   <message name="IDS_SETTINGS_ACCOUNT_MANAGER_ACCOUNT_REMOVED_MESSAGE" desc="Notification message after account removal.">
     <ph name="EMAIL">$1<ex>abcd@google.com</ex></ph> was removed from this device
   </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_LATENCY.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_LATENCY.png.sha1
new file mode 100644
index 0000000..952548c
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_LATENCY.png.sha1
@@ -0,0 +1 @@
+8d3e90b224faeaf73f44f7603005fec55751d0f6
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_RESOLUTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_RESOLUTION.png.sha1
new file mode 100644
index 0000000..be47c3d
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_RESOLUTION.png.sha1
@@ -0,0 +1 @@
+e3f815d34554a89cac6f8ff6495d7cf55d119660
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_RESOLVER_PRESENT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_RESOLVER_PRESENT.png.sha1
new file mode 100644
index 0000000..4e18d44
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_DNS_RESOLVER_PRESENT.png.sha1
@@ -0,0 +1 @@
+d6a31bc961c72c6cf7a337b3aac35909bf05a8d4
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_FAILED.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_FAILED.png.sha1
new file mode 100644
index 0000000..30eec67
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_FAILED.png.sha1
@@ -0,0 +1 @@
+a14700c25434eedb5cb5044c7f8d419c55da3761
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED.png.sha1
new file mode 100644
index 0000000..d60748d
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED.png.sha1
@@ -0,0 +1 @@
+d6fffef58f6cadeb2bc619d9b4dade4976b5f3f0
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION.png.sha1
new file mode 100644
index 0000000..db7b8a5
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION.png.sha1
@@ -0,0 +1 @@
+cf0771fcb7f48c0d1925642d421c5928e79c2470
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_LAN_CONNECTIVITY.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_LAN_CONNECTIVITY.png.sha1
new file mode 100644
index 0000000..95413a78
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_LAN_CONNECTIVITY.png.sha1
@@ -0,0 +1 @@
+e3916d9bc50e0aadba257e9d1497450a9f3fa5d6
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_NOT_RUN.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_NOT_RUN.png.sha1
new file mode 100644
index 0000000..55c7bcc
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_NOT_RUN.png.sha1
@@ -0,0 +1 @@
+19cb6a747506d33dd08178b2eb3f23e4e7cd8133
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_PASSED.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_PASSED.png.sha1
new file mode 100644
index 0000000..9dfb4bd
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_PASSED.png.sha1
@@ -0,0 +1 @@
+9ae35854439cca9d6352ee1551214f8d03de7891
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_RUN.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_RUN.png.sha1
new file mode 100644
index 0000000..41fef471
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_RUN.png.sha1
@@ -0,0 +1 @@
+af9a303d71a7e6f6990535d9d4621742b249ab19
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_RUN_ALL.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_RUN_ALL.png.sha1
new file mode 100644
index 0000000..0c9364a8
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_RUN_ALL.png.sha1
@@ -0,0 +1 @@
+52dffb800437a683e215b592e13cbff40655d53c
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_SIGNAL_STRENGTH.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_SIGNAL_STRENGTH.png.sha1
new file mode 100644
index 0000000..bb9db4d
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_DIAGNOSTICS_SIGNAL_STRENGTH.png.sha1
@@ -0,0 +1 @@
+fa426ab56d79e3802ef657e7d798375f084b44f2
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_UI_NETWORK_DIAGNOSTICS.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_UI_NETWORK_DIAGNOSTICS.png.sha1
new file mode 100644
index 0000000..4193fe2a
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_UI_NETWORK_DIAGNOSTICS.png.sha1
@@ -0,0 +1 @@
+8703ff17654615e35ccf9fffb788adfbb66722b7
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_PEOPLE_PIN_PROMPT_INVALID_PIN.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_PEOPLE_PIN_PROMPT_INVALID_PIN.png.sha1
new file mode 100644
index 0000000..9f2ec53
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_PEOPLE_PIN_PROMPT_INVALID_PIN.png.sha1
@@ -0,0 +1 @@
+777ba3f732d2222cfdda68d973c97f3fdec75a63
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 0688eff..f6039b9f 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -2087,6 +2087,12 @@
   <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_PIN_AUTOSUBMIT" desc="Option to enable PIN auto-submit">
+    Enable auto submit PIN
+  </message>
+  <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_PROMPT" desc="Text above a PIN input field that tells the user they need to submit their PIN to enable auto submit.">
+    Enter your PIN to enable auto submit
+  </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>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT.png.sha1
new file mode 100644
index 0000000..04b8ab4a
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT.png.sha1
@@ -0,0 +1 @@
+1560f2c59d6224d1db56c41f795c4f9fcff05208
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_PROMPT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_PROMPT.png.sha1
new file mode 100644
index 0000000..9f2ec53
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_PROMPT.png.sha1
@@ -0,0 +1 @@
+777ba3f732d2222cfdda68d973c97f3fdec75a63
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 459db53..ce5c688 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -513,9 +513,8 @@
   <message name="IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_TITLE" desc="Title for the dialog that asks the user which versions of a password to remove (device, Google Account or both).">
     Delete password?
   </message>
-  <!-- TODO(crbug.com/1102294): Inject the website in the string. -->
   <message name="IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_BODY" desc="Description message for the dialog that asks the user which versions of a password to remove (device, Google Account or both).">
-    Your password is stored on this device and in your Google Account. Which one do you want to delete?
+    Your password for <ph name="WEBSITE">&lt;b&gt;$1&lt;/b&gt;</ph> is stored on this device and in your Google Account. Which one do you want to delete?
   </message>
   <message name="IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_REMOVE_BUTTON_TEXT" desc="Text for the button that confirms the action in the dialog that asks the user which versions of a password to remove (device, Google Account or both).">
     Delete
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_BODY.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_BODY.png.sha1
index 7e3fc04..9fcc9a8d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_BODY.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_BODY.png.sha1
@@ -1 +1 @@
-551f6789b1660422ab08bdd839b383946603a956
\ No newline at end of file
+44462b2636bd411cd843d38282745059c3ca56ca
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a4998bd..0437a97 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -964,6 +964,8 @@
     "page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h",
     "page_load_metrics/observers/ad_metrics/frame_data.cc",
     "page_load_metrics/observers/ad_metrics/frame_data.h",
+    "page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc",
+    "page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h",
     "page_load_metrics/observers/amp_page_load_metrics_observer.cc",
     "page_load_metrics/observers/amp_page_load_metrics_observer.h",
     "page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc",
@@ -3290,16 +3292,6 @@
       "metrics/tab_stats_tracker.h",
       "metrics/tab_stats_tracker_delegate.h",
       "nearby_sharing/attachment.h",
-      "nearby_sharing/client/nearby_share_api_call_flow.h",
-      "nearby_sharing/client/nearby_share_api_call_flow_impl.cc",
-      "nearby_sharing/client/nearby_share_api_call_flow_impl.h",
-      "nearby_sharing/client/nearby_share_client.h",
-      "nearby_sharing/client/nearby_share_client_impl.cc",
-      "nearby_sharing/client/nearby_share_client_impl.h",
-      "nearby_sharing/client/nearby_share_request_error.cc",
-      "nearby_sharing/client/nearby_share_request_error.h",
-      "nearby_sharing/client/nearby_share_switches.cc",
-      "nearby_sharing/client/nearby_share_switches.h",
       "nearby_sharing/fast_initiation_manager.cc",
       "nearby_sharing/fast_initiation_manager.h",
       "nearby_sharing/file_attachment.cc",
@@ -3740,6 +3732,7 @@
       "//chrome/app/vector_icons",
       "//chrome/browser/media/kaleidoscope/mojom",
       "//chrome/browser/nearby_sharing/certificates",
+      "//chrome/browser/nearby_sharing/client",
       "//chrome/browser/nearby_sharing/instantmessaging/proto",
       "//chrome/browser/nearby_sharing/logging",
       "//chrome/browser/nearby_sharing/logging:util",
@@ -4819,10 +4812,7 @@
     ]
 
     if (is_android) {
-      deps += [
-        "//components/paint_preview/browser/android",
-        "//components/paint_preview/player/android",
-      ]
+      deps += [ "//components/paint_preview/player/android" ]
     }
   }
 
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 1cda006e..d60a18397 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -158,6 +158,7 @@
 #include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
 #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"  // nogncheck
+#include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"
 #include "chromeos/services/network_health/public/mojom/network_health.mojom.h"
 #endif
 
@@ -570,6 +571,10 @@
   RegisterWebUIControllerInterfaceBinder<
       chromeos::network_health::mojom::NetworkHealthService,
       chromeos::NetworkUI>(map);
+
+  RegisterWebUIControllerInterfaceBinder<
+      chromeos::network_diagnostics::mojom::NetworkDiagnosticsRoutines,
+      chromeos::NetworkUI>(map);
 #endif  // defined(OS_CHROMEOS)
 
 #if defined(OS_CHROMEOS) && !defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/chromeos/net/network_health/network_health_localized_strings.cc b/chrome/browser/chromeos/net/network_health/network_health_localized_strings.cc
index 2fedd22..4504d1c 100644
--- a/chrome/browser/chromeos/net/network_health/network_health_localized_strings.cc
+++ b/chrome/browser/chromeos/net/network_health/network_health_localized_strings.cc
@@ -14,6 +14,7 @@
 namespace {
 
 constexpr webui::LocalizedString kLocalizedStrings[] = {
+    // Network Health Summary Strings
     {"NetworkHealthState", IDS_NETWORK_HEALTH_STATE},
     {"NetworkHealthStateUninitialized", IDS_NETWORK_HEALTH_STATE_UNINITIALIZED},
     {"NetworkHealthStateDisabled", IDS_NETWORK_HEALTH_STATE_DISABLED},
@@ -23,6 +24,25 @@
     {"NetworkHealthStatePortal", IDS_NETWORK_HEALTH_STATE_PORTAL},
     {"NetworkHealthStateConnected", IDS_NETWORK_HEALTH_STATE_CONNECTED},
     {"NetworkHealthStateOnline", IDS_NETWORK_HEALTH_STATE_ONLINE},
+
+    // Network Diagnostics Strings
+    {"NetworkDiagnosticsLanConnectivity",
+     IDS_NETWORK_DIAGNOSTICS_LAN_CONNECTIVITY},
+    {"NetworkDiagnosticsSignalStrength",
+     IDS_NETWORK_DIAGNOSTICS_SIGNAL_STRENGTH},
+    {"NetworkDiagnosticsGatewayCanBePinged",
+     IDS_NETWORK_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED},
+    {"NetworkDiagnosticsHasSecureWiFiConnection",
+     IDS_NETWORK_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION},
+    {"NetworkDiagnosticsDnsResolverPresent",
+     IDS_NETWORK_DIAGNOSTICS_DNS_RESOLVER_PRESENT},
+    {"NetworkDiagnosticsDnsLatency", IDS_NETWORK_DIAGNOSTICS_DNS_LATENCY},
+    {"NetworkDiagnosticsDnsResolution", IDS_NETWORK_DIAGNOSTICS_DNS_RESOLUTION},
+    {"NetworkDiagnosticsPassed", IDS_NETWORK_DIAGNOSTICS_PASSED},
+    {"NetworkDiagnosticsFailed", IDS_NETWORK_DIAGNOSTICS_FAILED},
+    {"NetworkDiagnosticsNotRun", IDS_NETWORK_DIAGNOSTICS_NOT_RUN},
+    {"NetworkDiagnosticsRun", IDS_NETWORK_DIAGNOSTICS_RUN},
+    {"NetworkDiagnosticsRunAll", IDS_NETWORK_DIAGNOSTICS_RUN_ALL},
 };
 
 }  // namespace
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
index 95868bd..2d554e4a 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -661,6 +661,7 @@
     //   kReportDeviceVpdInfo
     //   kReportDeviceUsers
     //   kReportDeviceAppInfo
+    //   kReportDeviceSystemInfo
     //   kServiceAccountIdentity
     //   kSystemTimezonePolicy
     //   kVariationsRestrictParameter
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
index fb645da..32e5a6a 100644
--- a/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
+++ b/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
@@ -73,17 +73,26 @@
   kSigninProfile
 };
 
-// Describes a test configuration for the test suite.
-struct TestConfig {
+// Describes a test configuration for the test suite that runs one test per
+// profile.
+struct TestConfigPerProfile {
   // The profile for which PlatformKeysService should be tested.
   ProfileToUse profile_to_use;
 
-  // The token IDs that are expected to be available. This will be checked by
-  // the GetTokens test, and operation for these tokens will be performed by the
-  // other tests.
+  // The token IDs that are expected to be available for |profile_to_use|.
   std::vector<TokenId> token_ids;
 };
 
+// Describes a test configuration for the test suite that runs one test per
+// (profile, token) combination.
+struct TestConfigPerToken {
+  // The profile for which PlatformKeysService should be tested.
+  ProfileToUse profile_to_use;
+
+  // The token ID to perform the tests on.
+  TokenId token_id;
+};
+
 // Softoken NSS PKCS11 module (used for testing) allows only predefined key
 // attributes to be set and retrieved. Chaps supports setting and retrieving
 // custom attributes.
@@ -264,16 +273,15 @@
 };
 }  // namespace
 
-class PlatformKeysServiceBrowserTest
-    : public MixinBasedInProcessBrowserTest,
-      public ::testing::WithParamInterface<TestConfig> {
+class PlatformKeysServiceBrowserTestBase
+    : public MixinBasedInProcessBrowserTest {
  public:
-  PlatformKeysServiceBrowserTest() = default;
-  ~PlatformKeysServiceBrowserTest() override = default;
-  PlatformKeysServiceBrowserTest(const PlatformKeysServiceBrowserTest& other) =
-      delete;
-  PlatformKeysServiceBrowserTest& operator=(
-      const PlatformKeysServiceBrowserTest& other) = delete;
+  PlatformKeysServiceBrowserTestBase() = default;
+  PlatformKeysServiceBrowserTestBase(
+      const PlatformKeysServiceBrowserTestBase& other) = delete;
+  PlatformKeysServiceBrowserTestBase& operator=(
+      const PlatformKeysServiceBrowserTestBase& other) = delete;
+  ~PlatformKeysServiceBrowserTestBase() override = default;
 
   void SetUpInProcessBrowserTestFixture() override {
     MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
@@ -282,7 +290,7 @@
     // (empty) policy blobs are prepared in FakeSessionManagerClient.
     auto user_policy_update = user_policy_mixin_.RequestPolicyUpdate();
     auto device_policy_update = device_state_mixin_.RequestDevicePolicyUpdate();
-    if (GetParam().profile_to_use == ProfileToUse::kAffiliatedUserProfile) {
+    if (GetProfileToUse() == ProfileToUse::kAffiliatedUserProfile) {
       device_policy_update->policy_data()->add_device_affiliation_ids(
           kTestAffiliationId);
       user_policy_update->policy_data()->add_user_affiliation_ids(
@@ -293,7 +301,7 @@
   void SetUpOnMainThread() override {
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
 
-    if (GetParam().profile_to_use == ProfileToUse::kSigninProfile) {
+    if (GetProfileToUse() == ProfileToUse::kSigninProfile) {
       profile_ = ProfileHelper::GetSigninProfile();
     } else {
       ASSERT_TRUE(login_manager_mixin_.LoginAndWaitForActiveSession(
@@ -303,7 +311,7 @@
       base::RunLoop loop;
       GetNSSCertDatabaseForProfile(
           profile_,
-          base::BindRepeating(&PlatformKeysServiceBrowserTest::SetUserSlot,
+          base::BindRepeating(&PlatformKeysServiceBrowserTestBase::SetUserSlot,
                               base::Unretained(this), loop.QuitClosure()));
       loop.Run();
     }
@@ -326,6 +334,8 @@
   }
 
  protected:
+  virtual ProfileToUse GetProfileToUse() = 0;
+
   PlatformKeysService* platform_keys_service() {
     return platform_keys_service_;
   }
@@ -353,6 +363,30 @@
     return generate_key_waiter.public_key_spki_der();
   }
 
+  // Imports the certificate and key described by the |cert_filename| and
+  // |key_filename| files in |source_dir| into the Token |token_id|, then stores
+  // the resulting certificate in *|out_cert| and the SPKI of the public key in
+  // *|out_spki_der|. Should be wrapped in ASSERT_NO_FATAL_FAILURE.
+  void ImportCertAndKey(TokenId token_id,
+                        const base::FilePath& source_dir,
+                        const std::string& cert_filename,
+                        const std::string& key_filename,
+                        net::ScopedCERTCertificate* out_cert,
+                        std::string* out_spki_der) {
+    // Import testing key pair and certificate.
+    {
+      base::ScopedAllowBlockingForTesting allow_io;
+      net::ImportClientCertAndKeyFromFile(
+          source_dir, cert_filename, key_filename, GetSlot(token_id), out_cert);
+    }
+    CERTCertificate* cert = out_cert->get();
+    ASSERT_TRUE(cert);
+    ASSERT_GT(cert->derPublicKey.len, 0U);
+    *out_spki_der =
+        std::string(reinterpret_cast<const char*>(cert->derPublicKey.data),
+                    cert->derPublicKey.len);
+  }
+
  private:
   void SetUserSlot(const base::Closure& done_callback,
                    net::NSSCertDatabase* db) {
@@ -386,8 +420,23 @@
   std::unique_ptr<ScopedSoftokenAttrsMapping> scoped_softoken_attrs_mapping_;
 };
 
+class PlatformKeysServicePerProfileBrowserTest
+    : public PlatformKeysServiceBrowserTestBase,
+      public ::testing::WithParamInterface<TestConfigPerProfile> {
+ public:
+  PlatformKeysServicePerProfileBrowserTest() = default;
+  PlatformKeysServicePerProfileBrowserTest(
+      const PlatformKeysServicePerProfileBrowserTest& other) = delete;
+  PlatformKeysServicePerProfileBrowserTest& operator=(
+      const PlatformKeysServicePerProfileBrowserTest& other) = delete;
+  ~PlatformKeysServicePerProfileBrowserTest() override = default;
+
+ protected:
+  ProfileToUse GetProfileToUse() override { return GetParam().profile_to_use; }
+};
+
 // Tests that GetTokens() is callable and returns the expected tokens.
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest, GetTokens) {
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerProfileBrowserTest, GetTokens) {
   GetTokensExecutionWaiter get_tokens_waiter;
   platform_keys_service()->GetTokens(get_tokens_waiter.GetCallback());
   get_tokens_waiter.Wait();
@@ -398,210 +447,9 @@
               ::testing::UnorderedElementsAreArray(GetParam().token_ids));
 }
 
-// Generates a Rsa key pair and tests signing using that key pair.
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest, GenerateRsaAndSign) {
-  const std::string data_to_sign = "test";
-  const unsigned int kKeySize = 2048;
-  const HashAlgorithm hash_algorithm = HASH_ALGORITHM_SHA256;
-  const crypto::SignatureVerifier::SignatureAlgorithm signature_algorithm =
-      crypto::SignatureVerifier::RSA_PKCS1_SHA256;
-
-  for (TokenId token_id : GetParam().token_ids) {
-    GenerateKeyExecutionWaiter generate_key_waiter;
-    platform_keys_service()->GenerateRSAKey(token_id, kKeySize,
-                                            generate_key_waiter.GetCallback());
-    generate_key_waiter.Wait();
-    EXPECT_TRUE(generate_key_waiter.error_message().empty());
-
-    const std::string public_key_spki_der =
-        generate_key_waiter.public_key_spki_der();
-    EXPECT_FALSE(public_key_spki_der.empty());
-
-    SignExecutionWaiter sign_waiter;
-    platform_keys_service()->SignRSAPKCS1Digest(
-        token_id, data_to_sign, public_key_spki_der, hash_algorithm,
-        sign_waiter.GetCallback());
-    sign_waiter.Wait();
-    EXPECT_TRUE(sign_waiter.error_message().empty());
-
-    crypto::SignatureVerifier signature_verifier;
-    ASSERT_TRUE(signature_verifier.VerifyInit(
-        signature_algorithm,
-        base::as_bytes(base::make_span(sign_waiter.signature())),
-        base::as_bytes(base::make_span(public_key_spki_der))));
-    signature_verifier.VerifyUpdate(
-        base::as_bytes(base::make_span(data_to_sign)));
-    EXPECT_TRUE(signature_verifier.VerifyFinal());
-  }
-}
-
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest, SetAndGetKeyAttribute) {
-  // The attribute type to be set and retrieved using platform keys service.
-  const KeyAttributeType kAttributeType =
-      KeyAttributeType::CertificateProvisioningId;
-
-  for (TokenId token_id : GetParam().token_ids) {
-    const int token_id_as_int = static_cast<int>(token_id);
-    const std::string attribute_value =
-        base::StringPrintf("test%d", token_id_as_int);
-
-    // Generate key pair.
-    const std::string public_key_spki_der = GenerateKeyPair(token_id);
-    ASSERT_FALSE(public_key_spki_der.empty());
-
-    // Set key attribute.
-    SetAttributeForKeyExecutionWaiter set_attribute_for_key_execution_waiter;
-    platform_keys_service()->SetAttributeForKey(
-        token_id, public_key_spki_der, kAttributeType, attribute_value,
-        set_attribute_for_key_execution_waiter.GetCallback());
-    set_attribute_for_key_execution_waiter.Wait();
-
-    // Get key attribute.
-    GetAttributeForKeyExecutionWaiter get_attribute_for_key_execution_waiter;
-    platform_keys_service()->GetAttributeForKey(
-        token_id, public_key_spki_der, kAttributeType,
-        get_attribute_for_key_execution_waiter.GetCallback());
-    get_attribute_for_key_execution_waiter.Wait();
-
-    EXPECT_TRUE(get_attribute_for_key_execution_waiter.error_message().empty());
-    ASSERT_TRUE(get_attribute_for_key_execution_waiter.attribute_value());
-    EXPECT_EQ(get_attribute_for_key_execution_waiter.attribute_value().value(),
-              attribute_value);
-  }
-}
-
-// TODO(https://crbug.com/1073515): Add a test for an unset key attribute when
-// simulating chaps behavior is possible.
-
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest,
-                       GetKeyAttributeForNonExistingKey) {
-  const KeyAttributeType kAttributeType =
-      KeyAttributeType::CertificateProvisioningId;
-  const std::string kPublicKey = "Non Existing public key";
-
-  for (TokenId token_id : GetParam().token_ids) {
-    // Get key attribute.
-    GetAttributeForKeyExecutionWaiter get_attribute_for_key_execution_waiter;
-    platform_keys_service()->GetAttributeForKey(
-        token_id, kPublicKey, kAttributeType,
-        get_attribute_for_key_execution_waiter.GetCallback());
-    get_attribute_for_key_execution_waiter.Wait();
-
-    EXPECT_FALSE(
-        get_attribute_for_key_execution_waiter.error_message().empty());
-    ASSERT_FALSE(get_attribute_for_key_execution_waiter.attribute_value());
-  }
-}
-
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest,
-                       SetKeyAttributeForNonExistingKey) {
-  const KeyAttributeType kAttributeType =
-      KeyAttributeType::CertificateProvisioningId;
-  const std::string kAttributeValue = "test";
-  const std::string kPublicKey = "Non Existing public key";
-
-  for (TokenId token_id : GetParam().token_ids) {
-    // Set key attribute.
-    SetAttributeForKeyExecutionWaiter set_attribute_for_key_execution_waiter;
-    platform_keys_service()->SetAttributeForKey(
-        token_id, kPublicKey, kAttributeType, kAttributeValue,
-        set_attribute_for_key_execution_waiter.GetCallback());
-    set_attribute_for_key_execution_waiter.Wait();
-
-    EXPECT_FALSE(
-        set_attribute_for_key_execution_waiter.error_message().empty());
-  }
-}
-
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest,
-                       RemoveKeyWithNoMatchingCertificates) {
-  for (TokenId token_id : GetParam().token_ids) {
-    // Generate first key pair.
-    const std::string public_key_1 = GenerateKeyPair(token_id);
-    ASSERT_FALSE(public_key_1.empty());
-
-    // Generate second key pair.
-    const std::string public_key_2 = GenerateKeyPair(token_id);
-    ASSERT_FALSE(public_key_2.empty());
-
-    auto public_key_bytes_1 = base::as_bytes(base::make_span(public_key_1));
-    auto public_key_bytes_2 = base::as_bytes(base::make_span(public_key_2));
-    EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_1));
-    EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_2));
-
-    RemoveKeyExecutionWaiter remove_key_waiter;
-    platform_keys_service()->RemoveKey(token_id, public_key_1,
-                                       remove_key_waiter.GetCallback());
-    remove_key_waiter.Wait();
-
-    EXPECT_TRUE(remove_key_waiter.error_message().empty());
-    EXPECT_FALSE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_1));
-    EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_2));
-  }
-}
-
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest,
-                       RemoveKeyWithMatchingCertificate) {
-  for (TokenId token_id : GetParam().token_ids) {
-    PK11SlotInfo* const slot = GetSlot(token_id);
-
-    // Assert that there are no certificates before importing.
-    GetCertificatesExecutionWaiter get_certificates_waiter;
-    platform_keys_service()->GetCertificates(
-        token_id, get_certificates_waiter.GetCallback());
-    get_certificates_waiter.Wait();
-    ASSERT_EQ(get_certificates_waiter.matches().size(), 0U);
-
-    // Import testing key pair and certificate.
-    net::ScopedCERTCertificate cert;
-    {
-      base::ScopedAllowBlockingForTesting allow_io;
-      net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(),
-                                          "client_1.pem", "client_1.pk8", slot,
-                                          &cert);
-    }
-
-    // Assert that the certificate is imported correctly.
-    ASSERT_TRUE(cert.get());
-    GetCertificatesExecutionWaiter get_certificates_waiter_2;
-    platform_keys_service()->GetCertificates(
-        token_id, get_certificates_waiter_2.GetCallback());
-    get_certificates_waiter_2.Wait();
-    ASSERT_EQ(get_certificates_waiter_2.matches().size(), 1U);
-
-    ASSERT_GT(cert->derPublicKey.len, 0U);
-    std::string public_key(
-        reinterpret_cast<const char*>(cert->derPublicKey.data),
-        cert->derPublicKey.len);
-    auto public_key_bytes = base::as_bytes(base::make_span(public_key));
-    EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes));
-
-    // Try Removing the key pair.
-    RemoveKeyExecutionWaiter remove_key_waiter;
-    platform_keys_service()->RemoveKey(token_id, public_key,
-                                       remove_key_waiter.GetCallback());
-    remove_key_waiter.Wait();
-    EXPECT_FALSE(remove_key_waiter.error_message().empty());
-
-    // Assert that the certificate is not removed.
-    GetCertificatesExecutionWaiter get_certificates_waiter_3;
-    platform_keys_service()->GetCertificates(
-        token_id, get_certificates_waiter_3.GetCallback());
-    get_certificates_waiter_3.Wait();
-
-    net::CertificateList found_certs = get_certificates_waiter_3.matches();
-    ASSERT_EQ(found_certs.size(), 1U);
-    EXPECT_TRUE(
-        net::x509_util::IsSameCertificate(found_certs[0].get(), cert.get()));
-
-    // Assert that the key pair is not deleted.
-    EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes));
-  }
-}
-
 // Generates a key pair in tokens accessible from the profile under test and
 // retrieves them.
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest, GetAllKeys) {
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerProfileBrowserTest, GetAllKeys) {
   // Generate key pair in every token.
   std::map<TokenId, std::string> token_key_map;
   for (TokenId token_id : GetParam().token_ids) {
@@ -624,28 +472,320 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_P(PlatformKeysServiceBrowserTest,
-                       GetAllKeysWhenNoKeysGenerated) {
+// Imports the same key into all tokens. Verifies that key attributes are stored
+// per-token and don't leak between tokens.
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerProfileBrowserTest,
+                       KeyAttributesPerToken) {
+  // Import the same key pair + cert in every token, remember its SPKI.
+  std::string spki_der;
   for (TokenId token_id : GetParam().token_ids) {
-    GetAllKeysExecutionWaiter get_all_keys_waiter;
-    platform_keys_service()->GetAllKeys(token_id,
-                                        get_all_keys_waiter.GetCallback());
-    get_all_keys_waiter.Wait();
+    net::ScopedCERTCertificate cert;
+    std::string current_spki_der;
+    ASSERT_NO_FATAL_FAILURE(
+        ImportCertAndKey(token_id, net::GetTestCertsDirectory(), "client_1.pem",
+                         "client_1.pk8", &cert, &current_spki_der));
+    // The SPKI must be the same on every slot, because the same key was
+    // imported.
+    if (!spki_der.empty()) {
+      EXPECT_EQ(current_spki_der, spki_der);
+      continue;
+    }
+    spki_der = current_spki_der;
+  }
 
-    EXPECT_TRUE(get_all_keys_waiter.error_message().empty());
-    std::vector<std::string> public_keys = get_all_keys_waiter.public_keys();
-    EXPECT_TRUE(public_keys.empty());
+  // Set an attribute for the key on each token.
+  const KeyAttributeType kAttributeType =
+      KeyAttributeType::CertificateProvisioningId;
+  std::map<TokenId, std::string> token_to_value;
+  for (TokenId token_id : GetParam().token_ids) {
+    token_to_value[token_id] =
+        base::StringPrintf("test_value_%d", static_cast<int>(token_id));
+
+    // Set key attribute.
+    SetAttributeForKeyExecutionWaiter set_attr_waiter;
+    platform_keys_service()->SetAttributeForKey(
+        token_id, spki_der, kAttributeType, token_to_value[token_id],
+        set_attr_waiter.GetCallback());
+    set_attr_waiter.Wait();
+    EXPECT_TRUE(set_attr_waiter.error_message().empty());
+  }
+
+  // Verify the token-specific attribute value for the key on each token.
+  for (TokenId token_id : GetParam().token_ids) {
+    // Get key attribute.
+    GetAttributeForKeyExecutionWaiter get_attr_waiter;
+    platform_keys_service()->GetAttributeForKey(
+        token_id, spki_der, kAttributeType, get_attr_waiter.GetCallback());
+    get_attr_waiter.Wait();
+
+    EXPECT_TRUE(get_attr_waiter.error_message().empty());
+    ASSERT_TRUE(get_attr_waiter.attribute_value());
+    EXPECT_EQ(get_attr_waiter.attribute_value().value(),
+              token_to_value[token_id]);
   }
 }
 
 INSTANTIATE_TEST_SUITE_P(
     AllSupportedProfileTypes,
-    PlatformKeysServiceBrowserTest,
+    PlatformKeysServicePerProfileBrowserTest,
     ::testing::Values(
-        TestConfig{ProfileToUse::kSigninProfile, {TokenId::kSystem}},
-        TestConfig{ProfileToUse::kUnaffiliatedUserProfile, {TokenId::kUser}},
-        TestConfig{ProfileToUse::kAffiliatedUserProfile,
-                   {TokenId::kSystem, TokenId::kUser}}));
+        TestConfigPerProfile{ProfileToUse::kSigninProfile, {TokenId::kSystem}},
+        TestConfigPerProfile{ProfileToUse::kUnaffiliatedUserProfile,
+                             {TokenId::kUser}},
+        TestConfigPerProfile{ProfileToUse::kAffiliatedUserProfile,
+                             {TokenId::kUser, TokenId::kSystem}}));
 
+class PlatformKeysServicePerTokenBrowserTest
+    : public PlatformKeysServiceBrowserTestBase,
+      public ::testing::WithParamInterface<TestConfigPerToken> {
+ public:
+  PlatformKeysServicePerTokenBrowserTest() = default;
+  PlatformKeysServicePerTokenBrowserTest(
+      const PlatformKeysServicePerTokenBrowserTest& other) = delete;
+  PlatformKeysServicePerTokenBrowserTest& operator=(
+      const PlatformKeysServicePerTokenBrowserTest& other) = delete;
+  ~PlatformKeysServicePerTokenBrowserTest() override = default;
+
+ protected:
+  ProfileToUse GetProfileToUse() override { return GetParam().profile_to_use; }
+};
+
+// Generates a Rsa key pair and tests signing using that key pair.
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       GenerateRsaAndSign) {
+  const std::string kDataToSign = "test";
+  const unsigned int kKeySize = 2048;
+  const HashAlgorithm kHashAlgorithm = HASH_ALGORITHM_SHA256;
+  const crypto::SignatureVerifier::SignatureAlgorithm kSignatureAlgorithm =
+      crypto::SignatureVerifier::RSA_PKCS1_SHA256;
+
+  const TokenId token_id = GetParam().token_id;
+  GenerateKeyExecutionWaiter generate_key_waiter;
+  platform_keys_service()->GenerateRSAKey(token_id, kKeySize,
+                                          generate_key_waiter.GetCallback());
+  generate_key_waiter.Wait();
+  EXPECT_TRUE(generate_key_waiter.error_message().empty());
+
+  const std::string public_key_spki_der =
+      generate_key_waiter.public_key_spki_der();
+  EXPECT_FALSE(public_key_spki_der.empty());
+
+  SignExecutionWaiter sign_waiter;
+  platform_keys_service()->SignRSAPKCS1Digest(
+      token_id, kDataToSign, public_key_spki_der, kHashAlgorithm,
+      sign_waiter.GetCallback());
+  sign_waiter.Wait();
+  EXPECT_TRUE(sign_waiter.error_message().empty());
+
+  crypto::SignatureVerifier signature_verifier;
+  ASSERT_TRUE(signature_verifier.VerifyInit(
+      kSignatureAlgorithm,
+      base::as_bytes(base::make_span(sign_waiter.signature())),
+      base::as_bytes(base::make_span(public_key_spki_der))));
+  signature_verifier.VerifyUpdate(base::as_bytes(base::make_span(kDataToSign)));
+  EXPECT_TRUE(signature_verifier.VerifyFinal());
+}
+
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       SetAndGetKeyAttribute) {
+  // The attribute type to be set and retrieved using platform keys service.
+  const KeyAttributeType kAttributeType =
+      KeyAttributeType::CertificateProvisioningId;
+  const TokenId token_id = GetParam().token_id;
+  const std::string kAttributeValue = "test_attr_value";
+
+  // Generate key pair.
+  const std::string public_key_spki_der = GenerateKeyPair(token_id);
+  ASSERT_FALSE(public_key_spki_der.empty());
+
+  // Set key attribute.
+  SetAttributeForKeyExecutionWaiter set_attribute_for_key_execution_waiter;
+  platform_keys_service()->SetAttributeForKey(
+      token_id, public_key_spki_der, kAttributeType, kAttributeValue,
+      set_attribute_for_key_execution_waiter.GetCallback());
+  set_attribute_for_key_execution_waiter.Wait();
+
+  // Get key attribute.
+  GetAttributeForKeyExecutionWaiter get_attribute_for_key_execution_waiter;
+  platform_keys_service()->GetAttributeForKey(
+      token_id, public_key_spki_der, kAttributeType,
+      get_attribute_for_key_execution_waiter.GetCallback());
+  get_attribute_for_key_execution_waiter.Wait();
+
+  EXPECT_TRUE(get_attribute_for_key_execution_waiter.error_message().empty());
+  ASSERT_TRUE(get_attribute_for_key_execution_waiter.attribute_value());
+  EXPECT_EQ(get_attribute_for_key_execution_waiter.attribute_value().value(),
+            kAttributeValue);
+}
+
+// TODO(https://crbug.com/1073515): Add a test for an unset key attribute when
+// simulating chaps behavior is possible.
+
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       GetKeyAttributeForNonExistingKey) {
+  const KeyAttributeType kAttributeType =
+      KeyAttributeType::CertificateProvisioningId;
+  const TokenId token_id = GetParam().token_id;
+  const std::string kPublicKey = "Non Existing public key";
+
+  // Get key attribute.
+  GetAttributeForKeyExecutionWaiter get_attribute_for_key_execution_waiter;
+  platform_keys_service()->GetAttributeForKey(
+      token_id, kPublicKey, kAttributeType,
+      get_attribute_for_key_execution_waiter.GetCallback());
+  get_attribute_for_key_execution_waiter.Wait();
+
+  EXPECT_FALSE(get_attribute_for_key_execution_waiter.error_message().empty());
+  EXPECT_FALSE(get_attribute_for_key_execution_waiter.attribute_value());
+}
+
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       SetKeyAttributeForNonExistingKey) {
+  const KeyAttributeType kAttributeType =
+      KeyAttributeType::CertificateProvisioningId;
+  const TokenId token_id = GetParam().token_id;
+  const std::string kAttributeValue = "test";
+  const std::string kPublicKey = "Non Existing public key";
+
+  // Set key attribute.
+  SetAttributeForKeyExecutionWaiter set_attribute_for_key_execution_waiter;
+  platform_keys_service()->SetAttributeForKey(
+      token_id, kPublicKey, kAttributeType, kAttributeValue,
+      set_attribute_for_key_execution_waiter.GetCallback());
+  set_attribute_for_key_execution_waiter.Wait();
+
+  EXPECT_FALSE(set_attribute_for_key_execution_waiter.error_message().empty());
+}
+
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       RemoveKeyWithNoMatchingCertificates) {
+  const TokenId token_id = GetParam().token_id;
+
+  // Generate first key pair.
+  const std::string public_key_1 = GenerateKeyPair(token_id);
+  ASSERT_FALSE(public_key_1.empty());
+
+  // Generate second key pair.
+  const std::string public_key_2 = GenerateKeyPair(token_id);
+  ASSERT_FALSE(public_key_2.empty());
+
+  auto public_key_bytes_1 = base::as_bytes(base::make_span(public_key_1));
+  auto public_key_bytes_2 = base::as_bytes(base::make_span(public_key_2));
+  EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_1));
+  EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_2));
+
+  RemoveKeyExecutionWaiter remove_key_waiter;
+  platform_keys_service()->RemoveKey(token_id, public_key_1,
+                                     remove_key_waiter.GetCallback());
+  remove_key_waiter.Wait();
+
+  EXPECT_TRUE(remove_key_waiter.error_message().empty());
+  EXPECT_FALSE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_1));
+  EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes_2));
+}
+
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       RemoveKeyWithMatchingCertificate) {
+  const TokenId token_id = GetParam().token_id;
+
+  // Assert that there are no certificates before importing.
+  GetCertificatesExecutionWaiter get_certificates_waiter;
+  platform_keys_service()->GetCertificates(
+      token_id, get_certificates_waiter.GetCallback());
+  get_certificates_waiter.Wait();
+  ASSERT_EQ(get_certificates_waiter.matches().size(), 0U);
+
+  net::ScopedCERTCertificate cert;
+  std::string public_key;
+  ASSERT_NO_FATAL_FAILURE(
+      ImportCertAndKey(token_id, net::GetTestCertsDirectory(), "client_1.pem",
+                       "client_1.pk8", &cert, &public_key));
+
+  // Assert that the certificate is imported correctly.
+  ASSERT_TRUE(cert.get());
+  GetCertificatesExecutionWaiter get_certificates_waiter_2;
+  platform_keys_service()->GetCertificates(
+      token_id, get_certificates_waiter_2.GetCallback());
+  get_certificates_waiter_2.Wait();
+  ASSERT_EQ(get_certificates_waiter_2.matches().size(), 1U);
+
+  auto public_key_bytes = base::as_bytes(base::make_span(public_key));
+  EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes));
+
+  // Try Removing the key pair.
+  RemoveKeyExecutionWaiter remove_key_waiter;
+  platform_keys_service()->RemoveKey(token_id, public_key,
+                                     remove_key_waiter.GetCallback());
+  remove_key_waiter.Wait();
+  EXPECT_FALSE(remove_key_waiter.error_message().empty());
+
+  // Assert that the certificate is not removed.
+  GetCertificatesExecutionWaiter get_certificates_waiter_3;
+  platform_keys_service()->GetCertificates(
+      token_id, get_certificates_waiter_3.GetCallback());
+  get_certificates_waiter_3.Wait();
+
+  net::CertificateList found_certs = get_certificates_waiter_3.matches();
+  ASSERT_EQ(found_certs.size(), 1U);
+  EXPECT_TRUE(
+      net::x509_util::IsSameCertificate(found_certs[0].get(), cert.get()));
+
+  // Assert that the key pair is not deleted.
+  EXPECT_TRUE(crypto::FindNSSKeyFromPublicKeyInfo(public_key_bytes));
+}
+
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerTokenBrowserTest,
+                       GetAllKeysWhenNoKeysGenerated) {
+  const TokenId token_id = GetParam().token_id;
+  GetAllKeysExecutionWaiter get_all_keys_waiter;
+  platform_keys_service()->GetAllKeys(token_id,
+                                      get_all_keys_waiter.GetCallback());
+  get_all_keys_waiter.Wait();
+
+  EXPECT_TRUE(get_all_keys_waiter.error_message().empty());
+  std::vector<std::string> public_keys = get_all_keys_waiter.public_keys();
+  EXPECT_TRUE(public_keys.empty());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    AllSupportedProfilesAndTokensTypes,
+    PlatformKeysServicePerTokenBrowserTest,
+    ::testing::Values(TestConfigPerToken{ProfileToUse::kSigninProfile,
+                                         TokenId::kSystem},
+                      TestConfigPerToken{ProfileToUse::kUnaffiliatedUserProfile,
+                                         TokenId::kUser},
+                      TestConfigPerToken{ProfileToUse::kAffiliatedUserProfile,
+                                         TokenId::kSystem},
+                      TestConfigPerToken{ProfileToUse::kAffiliatedUserProfile,
+                                         TokenId::kUser}));
+
+// PlatformKeysServicePerUnavailableTokenBrowserTest is essentially the same as
+// PlatformKeysServicePerTokenBrowserTest but contains different test cases
+// (testing that the token is not available) and runs on a different set of
+// (profile, token) pairs accordingly.
+using PlatformKeysServicePerUnavailableTokenBrowserTest =
+    PlatformKeysServicePerTokenBrowserTest;
+
+// Uses GenerateRSAKey as an example operation that should fail because the
+// token is not available.
+IN_PROC_BROWSER_TEST_P(PlatformKeysServicePerUnavailableTokenBrowserTest,
+                       GenerateRsa) {
+  const unsigned int kKeySize = 2048;
+
+  const TokenId token_id = GetParam().token_id;
+  GenerateKeyExecutionWaiter generate_key_waiter;
+  platform_keys_service()->GenerateRSAKey(token_id, kKeySize,
+                                          generate_key_waiter.GetCallback());
+  generate_key_waiter.Wait();
+  EXPECT_FALSE(generate_key_waiter.error_message().empty());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    AllSupportedProfilesAndTokensTypes,
+    PlatformKeysServicePerUnavailableTokenBrowserTest,
+    ::testing::Values(TestConfigPerToken{ProfileToUse::kSigninProfile,
+                                         TokenId::kUser},
+                      TestConfigPerToken{ProfileToUse::kUnaffiliatedUserProfile,
+                                         TokenId::kSystem}));
 }  // namespace platform_keys
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 0623b17..4e3e5ed 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -759,6 +759,11 @@
                     POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
                     base::Value(container.report_vpd_info()), nullptr);
     }
+    if (container.has_report_system_info()) {
+      policies->Set(key::kReportDeviceSystemInfo, POLICY_LEVEL_MANDATORY,
+                    POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+                    base::Value(container.report_system_info()), nullptr);
+    }
   }
 
   if (policy.has_device_heartbeat_settings()) {
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
index faa4df3..1894978 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
@@ -715,11 +715,13 @@
 
   void FetchCrosHealthdData(
       const policy::DeviceStatusCollector::CrosHealthdDataFetcher&
-          cros_healthd_data_fetcher) {
+          cros_healthd_data_fetcher,
+      bool report_system_info,
+      bool report_vpd_info) {
     cros_healthd_data_fetcher.Run(
         CrosHealthdCollectionMode::kFull,
         base::BindOnce(&DeviceStatusCollectorState::OnCrosHealthdDataReceived,
-                       this));
+                       this, report_system_info, report_vpd_info));
   }
 
   void FetchEMMCLifeTime(
@@ -819,6 +821,8 @@
 
   // Stores the contents of |probe_result| and |samples| to |response_params_|.
   void OnCrosHealthdDataReceived(
+      bool report_system_info,
+      bool report_vpd_info,
       chromeos::cros_healthd::mojom::TelemetryInfoPtr probe_result,
       const base::circular_deque<std::unique_ptr<SampledData>>& samples) {
     namespace cros_healthd = chromeos::cros_healthd::mojom;
@@ -885,27 +889,6 @@
       }
     }
 
-    // Process CachedVpdResult.
-    const auto& vpd_result = probe_result->vpd_result;
-    if (!vpd_result.is_null()) {
-      switch (vpd_result->which()) {
-        case cros_healthd::CachedVpdResult::Tag::ERROR: {
-          LOG(ERROR) << "cros_healthd: Error getting cached VPD info: "
-                     << vpd_result->get_error()->msg;
-          break;
-        }
-
-        case cros_healthd::CachedVpdResult::Tag::VPD_INFO: {
-          const auto& vpd_info = vpd_result->get_vpd_info();
-          em::SystemStatus* const system_status_out =
-              response_params_.device_status->mutable_system_status();
-          if (vpd_info->sku_number.has_value())
-            system_status_out->set_vpd_sku_number(vpd_info->sku_number.value());
-          break;
-        }
-      }
-    }
-
     // Process BatteryResult.
     const auto& battery_result = probe_result->battery_result;
     if (!battery_result.is_null()) {
@@ -1140,6 +1123,62 @@
         }
       }
     }
+
+    // Process SystemResult.
+    const auto& system_result = probe_result->system_result;
+    if (!system_result.is_null()) {
+      switch (system_result->which()) {
+        case cros_healthd::SystemResult::Tag::ERROR: {
+          LOG(ERROR) << "cros_healthd: Error getting system info: "
+                     << system_result->get_error()->msg;
+          break;
+        }
+
+        case cros_healthd::SystemResult::Tag::SYSTEM_INFO: {
+          const auto& system_info = system_result->get_system_info();
+          em::SystemStatus* const system_status_out =
+              response_params_.device_status->mutable_system_status();
+          if (report_vpd_info) {
+            if (system_info->first_power_date.has_value()) {
+              system_status_out->set_first_power_date(
+                  system_info->first_power_date.value());
+            }
+            if (system_info->manufacture_date.has_value()) {
+              system_status_out->set_manufacture_date(
+                  system_info->manufacture_date.value());
+            }
+            if (system_info->product_sku_number.has_value()) {
+              system_status_out->set_vpd_sku_number(
+                  system_info->product_sku_number.value());
+            }
+          }
+          if (report_system_info) {
+            system_status_out->set_marketing_name(system_info->marketing_name);
+            if (system_info->bios_version.has_value()) {
+              system_status_out->set_bios_version(
+                  system_info->bios_version.value());
+            }
+            if (system_info->board_name.has_value()) {
+              system_status_out->set_board_name(
+                  system_info->board_name.value());
+            }
+            if (system_info->board_version.has_value()) {
+              system_status_out->set_board_version(
+                  system_info->board_version.value());
+            }
+            if (system_info->chassis_type) {
+              system_status_out->set_chassis_type(
+                  system_info->chassis_type->value);
+            }
+            if (system_info->product_name.has_value()) {
+              system_status_out->set_product_name(
+                  system_info->product_name.value());
+            }
+          }
+          break;
+        }
+      }
+    }
   }
 
   void OnEMMCLifetimeReceived(const em::DiskLifetimeEstimation& est) {
@@ -1328,6 +1367,8 @@
       chromeos::kReportDeviceVpdInfo, callback);
   app_info_subscription_ = cros_settings_->AddSettingsObserver(
       chromeos::kReportDeviceAppInfo, callback);
+  system_info_subscription_ = cros_settings_->AddSettingsObserver(
+      chromeos::kReportDeviceSystemInfo, callback);
   stats_reporting_pref_subscription_ = cros_settings_->AddSettingsObserver(
       chromeos::kStatsReportingPref, callback);
 
@@ -1480,6 +1521,10 @@
                                   &report_bluetooth_info_)) {
     report_bluetooth_info_ = false;
   }
+  if (!cros_settings_->GetBoolean(chromeos::kReportDeviceSystemInfo,
+                                  &report_system_info_)) {
+    report_system_info_ = false;
+  }
   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceFanInfo,
                                   &report_fan_info_)) {
     report_fan_info_ = false;
@@ -1771,8 +1816,8 @@
   SamplingProbeResultCallback completion_callback;
   switch (mode) {
     case CrosHealthdCollectionMode::kFull: {
-      if (report_vpd_info_)
-        categories_to_probe.push_back(ProbeCategoryEnum::kCachedVpdData);
+      if (report_vpd_info_ || report_system_info_)
+        categories_to_probe.push_back(ProbeCategoryEnum::kSystem);
       if (report_storage_status_) {
         categories_to_probe.push_back(
             ProbeCategoryEnum::kNonRemovableBlockDevices);
@@ -1823,7 +1868,8 @@
 bool DeviceStatusCollector::ShouldFetchCrosHealthdData() const {
   return report_vpd_info_ || report_power_status_ || report_storage_status_ ||
          report_cpu_info_ || report_timezone_info_ || report_memory_info_ ||
-         report_backlight_info_ || report_fan_info_ || report_bluetooth_info_;
+         report_backlight_info_ || report_fan_info_ || report_bluetooth_info_ ||
+         report_system_info_;
 }
 
 void DeviceStatusCollector::ReportingUsersChanged() {
@@ -2155,7 +2201,8 @@
     state->FetchEMMCLifeTime(emmc_lifetime_fetcher_);
 
   if (ShouldFetchCrosHealthdData()) {
-    state->FetchCrosHealthdData(cros_healthd_data_fetcher_);
+    state->FetchCrosHealthdData(cros_healthd_data_fetcher_, report_system_info_,
+                                report_vpd_info_);
   } else {
     // Sample CPU temperature in a background thread.
     state->SampleCPUTempInfo(cpu_temp_fetcher_);
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.h b/chrome/browser/chromeos/policy/status_collector/device_status_collector.h
index 89a075e..596e242 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.h
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.h
@@ -455,6 +455,7 @@
   bool report_fan_info_ = false;
   bool report_vpd_info_ = false;
   bool report_app_info_ = false;
+  bool report_system_info_ = false;
   bool stat_reporting_pref_ = false;
 
   std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
@@ -496,6 +497,8 @@
   std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
       vpd_info_subscription_;
   std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
+      system_info_subscription_;
+  std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
       app_info_subscription_;
   std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
       stats_reporting_pref_subscription_;
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
index 8c48ee9..9325de3 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -142,8 +142,16 @@
     kExpectedBatteryCurrentNow / 1000.0;  // (A)
 constexpr char kFakeBatteryTechnology[] = "fake_battery_technology";
 constexpr char kFakeBatteryStatus[] = "fake_battery_status";
-// Cached VPD test values:
-constexpr char kFakeSkuNumber[] = "fake_sku_number";
+// System test values:
+const char kFakeFirstPowerDate[] = "2020-40";
+const char kFakeManufactureDate[] = "2019-01-01";
+const char kFakeSkuNumber[] = "ABCD&^A";
+constexpr char kFakeMarketingName[] = "Latitude 1234 Chromebook Enterprise";
+constexpr char kFakeBiosVersion[] = "Google_BoardName.12200.68.0";
+constexpr char kFakeBoardName[] = "BoardName";
+constexpr char kFakeBoardVersion[] = "rev1234";
+constexpr uint64_t kFakeChassisType = 9;
+constexpr char kFakeProductName[] = "ProductName";
 // CPU test values:
 constexpr uint32_t kFakeNumTotalThreads = 8;
 constexpr char kFakeModelName[] = "fake_cpu_model_name";
@@ -489,9 +497,13 @@
       std::move(storage_vector));
 }
 
-cros_healthd::CachedVpdResultPtr CreateVpdResult() {
-  return cros_healthd::CachedVpdResult::NewVpdInfo(
-      cros_healthd::CachedVpdInfo::New(kFakeSkuNumber));
+cros_healthd::SystemResultPtr CreateSystemResult() {
+  return cros_healthd::SystemResult::NewSystemInfo(
+      cros_healthd::SystemInfo::New(
+          kFakeFirstPowerDate, kFakeManufactureDate, kFakeSkuNumber,
+          kFakeMarketingName, kFakeBiosVersion, kFakeBoardName,
+          kFakeBoardVersion, cros_healthd::UInt64Value::New(kFakeChassisType),
+          kFakeProductName));
 }
 
 std::vector<cros_healthd::CpuCStateInfoPtr> CreateCStateInfo() {
@@ -594,7 +606,7 @@
       cros_healthd::TelemetryInfo fake_info;
       fake_info.battery_result = CreateBatteryResult();
       fake_info.block_device_result = CreateBlockDeviceResult();
-      fake_info.vpd_result = CreateVpdResult();
+      fake_info.system_result = CreateSystemResult();
       fake_info.cpu_result = CreateCpuResult();
       fake_info.timezone_result = CreateTimezoneResult();
       fake_info.memory_result = CreateMemoryResult();
@@ -3033,6 +3045,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceBluetoothInfo, false);
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceSystemInfo, false);
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceVpdInfo, false);
   GetStatus();
   ASSERT_EQ(device_status_.cpu_info_size(), 0);
@@ -3063,6 +3077,8 @@
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceBluetoothInfo, true);
   scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceSystemInfo, true);
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
       chromeos::kReportDeviceVpdInfo, true);
   GetStatus();
 
@@ -3114,9 +3130,20 @@
   EXPECT_EQ(disk.discard_time_seconds_since_last_boot(),
             kFakeStorageDiscardTimeSeconds);
 
-  // Verify the Cached VPD.
+  // Verify the system info.
   ASSERT_TRUE(device_status_.has_system_status());
+  EXPECT_EQ(device_status_.system_status().first_power_date(),
+            kFakeFirstPowerDate);
+  EXPECT_EQ(device_status_.system_status().manufacture_date(),
+            kFakeManufactureDate);
   EXPECT_EQ(device_status_.system_status().vpd_sku_number(), kFakeSkuNumber);
+  EXPECT_EQ(device_status_.system_status().marketing_name(),
+            kFakeMarketingName);
+  EXPECT_EQ(device_status_.system_status().bios_version(), kFakeBiosVersion);
+  EXPECT_EQ(device_status_.system_status().board_name(), kFakeBoardName);
+  EXPECT_EQ(device_status_.system_status().board_version(), kFakeBoardVersion);
+  EXPECT_EQ(device_status_.system_status().chassis_type(), kFakeChassisType);
+  EXPECT_EQ(device_status_.system_status().product_name(), kFakeProductName);
 
   // Verify the CPU data.
   ASSERT_TRUE(device_status_.has_global_cpu_info());
@@ -3236,6 +3263,65 @@
   EXPECT_EQ(device_status_.fan_info_size(), 0);
 }
 
+TEST_F(DeviceStatusCollectorTest, TestCrosHealthdVpdAndSystemInfo) {
+  // Create a fake response from cros_healthd and populate it with some
+  // arbitrary values.
+  auto options = CreateEmptyDeviceStatusCollectorOptions();
+  options->cros_healthd_data_fetcher =
+      base::BindRepeating(&FetchFakeFullCrosHealthdData);
+  RestartStatusCollector(std::move(options));
+
+  // If the ReportDeviceHardwareStatus policy is false, the policies
+  // corresponding to cros_healthd data are ignored. The policy is true by
+  // default, but set it explicitly to ensure the other policies are tested.
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceHardwareStatus, true);
+
+  // When the vpd reporting policy is turned on and the system reporting
+  // property is turned off, we only expect the protobuf to only have vpd info.
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceSystemInfo, false);
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceVpdInfo, true);
+  GetStatus();
+
+  // Verify the only vpd info is populated.
+  ASSERT_TRUE(device_status_.has_system_status());
+  EXPECT_EQ(device_status_.system_status().first_power_date(),
+            kFakeFirstPowerDate);
+  EXPECT_EQ(device_status_.system_status().manufacture_date(),
+            kFakeManufactureDate);
+  EXPECT_EQ(device_status_.system_status().vpd_sku_number(), kFakeSkuNumber);
+  ASSERT_FALSE(device_status_.system_status().has_marketing_name());
+  ASSERT_FALSE(device_status_.system_status().has_bios_version());
+  ASSERT_FALSE(device_status_.system_status().has_board_name());
+  ASSERT_FALSE(device_status_.system_status().has_board_version());
+  ASSERT_FALSE(device_status_.system_status().has_chassis_type());
+  ASSERT_FALSE(device_status_.system_status().has_product_name());
+
+  // When the system reporting policy is turned on and the vpd reporting policy
+  // is turned off, we expect the protobuf to have all system info except the
+  // subset of vpd info.
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceSystemInfo, true);
+  scoped_testing_cros_settings_.device_settings()->SetBoolean(
+      chromeos::kReportDeviceVpdInfo, false);
+  GetStatus();
+
+  // Verify all system info except vpd info exists.
+  ASSERT_TRUE(device_status_.has_system_status());
+  ASSERT_FALSE(device_status_.system_status().has_first_power_date());
+  ASSERT_FALSE(device_status_.system_status().has_manufacture_date());
+  ASSERT_FALSE(device_status_.system_status().has_vpd_sku_number());
+  EXPECT_EQ(device_status_.system_status().marketing_name(),
+            kFakeMarketingName);
+  EXPECT_EQ(device_status_.system_status().bios_version(), kFakeBiosVersion);
+  EXPECT_EQ(device_status_.system_status().board_name(), kFakeBoardName);
+  EXPECT_EQ(device_status_.system_status().board_version(), kFakeBoardVersion);
+  EXPECT_EQ(device_status_.system_status().chassis_type(), kFakeChassisType);
+  EXPECT_EQ(device_status_.system_status().product_name(), kFakeProductName);
+}
+
 TEST_F(DeviceStatusCollectorTest, GenerateAppInfo) {
   const AccountId account_id(AccountId::FromUserEmail("user0@managed.com"));
   MockRegularUserWithAffiliation(account_id, true);
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index f2fadd0..85e3575 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -135,6 +135,7 @@
     kReportDeviceVersionInfo,
     kReportDeviceVpdInfo,
     kReportDeviceAppInfo,
+    kReportDeviceSystemInfo,
     kReportOsUpdateStatus,
     kReportRunningKioskApp,
     kReportUploadFrequency,
@@ -625,6 +626,10 @@
       new_values_cache->SetBoolean(kReportDeviceVpdInfo,
                                    reporting_policy.report_vpd_info());
     }
+    if (reporting_policy.has_report_system_info()) {
+      new_values_cache->SetBoolean(kReportDeviceSystemInfo,
+                                   reporting_policy.report_system_info());
+    }
   }
 }
 
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java
index 2bb9956..3590d0e9 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java
@@ -14,9 +14,9 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.CheckBox;
-import android.widget.LinearLayout;
 import android.widget.RadioGroup;
 import android.widget.RadioGroup.OnCheckedChangeListener;
+import android.widget.ScrollView;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
@@ -33,7 +33,7 @@
 /**
  * The custom view in the download later dialog.
  */
-public class DownloadLaterDialogView extends LinearLayout implements OnCheckedChangeListener {
+public class DownloadLaterDialogView extends ScrollView implements OnCheckedChangeListener {
     private Controller mController;
 
     private RadioButtonWithDescription mDownloadNow;
diff --git a/chrome/browser/enterprise/reporting/policy_info_unittest.cc b/chrome/browser/enterprise/reporting/policy_info_unittest.cc
index 17fda2a..f7600e51 100644
--- a/chrome/browser/enterprise/reporting/policy_info_unittest.cc
+++ b/chrome/browser/enterprise/reporting/policy_info_unittest.cc
@@ -93,11 +93,10 @@
 TEST_F(PolicyInfoTest, ChromePolicy) {
   policy_map()->Set(kPolicyName1, policy::POLICY_LEVEL_MANDATORY,
                     policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-                    std::make_unique<base::Value>(std::vector<base::Value>()),
-                    nullptr);
+                    base::Value(std::vector<base::Value>()), nullptr);
   policy_map()->Set(kPolicyName2, policy::POLICY_LEVEL_RECOMMENDED,
                     policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_MERGED,
-                    std::make_unique<base::Value>(true), nullptr);
+                    base::Value(true), nullptr);
   em::ChromeUserProfileInfo profile_info;
 
   EXPECT_CALL(*policy_service(), GetPolicies(_));
@@ -147,8 +146,8 @@
 
   extension_policy_map()->Set(kPolicyName1, policy::POLICY_LEVEL_MANDATORY,
                               policy::POLICY_SCOPE_MACHINE,
-                              policy::POLICY_SOURCE_PLATFORM,
-                              std::make_unique<base::Value>(3), nullptr);
+                              policy::POLICY_SOURCE_PLATFORM, base::Value(3),
+                              nullptr);
   em::ChromeUserProfileInfo profile_info;
   auto client =
       std::make_unique<policy::ChromePolicyConversionsClient>(profile());
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc
index ec72a41d..62d5b2a 100644
--- a/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -716,8 +716,7 @@
   PolicyMap policies;
   policies.Set(policy::key::kExtensionInstallForcelist,
                policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-               policy::POLICY_SOURCE_CLOUD, forcelist.CreateDeepCopy(),
-               nullptr);
+               policy::POLICY_SOURCE_CLOUD, forcelist.Clone(), nullptr);
   extensions::TestExtensionRegistryObserver install_observer(registry);
   UpdateProviderPolicy(policies);
   install_observer.WaitForExtensionWillBeInstalled();
@@ -821,8 +820,7 @@
   PolicyMap policies;
   policies.Set(policy::key::kExtensionInstallForcelist,
                policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-               policy::POLICY_SOURCE_CLOUD, forcelist.CreateDeepCopy(),
-               nullptr);
+               policy::POLICY_SOURCE_CLOUD, forcelist.Clone(), nullptr);
   extensions::TestExtensionRegistryObserver install_observer(registry);
   UpdateProviderPolicy(policies);
 
@@ -862,8 +860,7 @@
   // and force enable it too.
   policies.Set(policy::key::kExtensionInstallForcelist,
                policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-               policy::POLICY_SOURCE_CLOUD, forcelist.CreateDeepCopy(),
-               nullptr);
+               policy::POLICY_SOURCE_CLOUD, forcelist.Clone(), nullptr);
 
   extensions::TestExtensionRegistryObserver extension_observer(registry);
   UpdateProviderPolicy(policies);
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_policy_handler_unittest.cc b/chrome/browser/extensions/api/messaging/native_messaging_policy_handler_unittest.cc
index 9176212..8ae6e87 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_policy_handler_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_messaging_policy_handler_unittest.cc
@@ -24,7 +24,7 @@
 
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, list.Clone(), nullptr);
   {
     policy::PolicyErrorMap errors;
     EXPECT_TRUE(handler.CheckPolicySettings(policy_map, &errors));
@@ -34,7 +34,7 @@
   list.AppendString("test.a.b");
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, list.Clone(), nullptr);
   {
     policy::PolicyErrorMap errors;
     EXPECT_TRUE(handler.CheckPolicySettings(policy_map, &errors));
@@ -44,7 +44,7 @@
   list.AppendString("*");
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, list.Clone(), nullptr);
   {
     policy::PolicyErrorMap errors;
     EXPECT_TRUE(handler.CheckPolicySettings(policy_map, &errors));
@@ -54,7 +54,7 @@
   list.AppendString("invalid Name");
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, list.Clone(), nullptr);
   {
     policy::PolicyErrorMap errors;
     EXPECT_TRUE(handler.CheckPolicySettings(policy_map, &errors));
@@ -78,7 +78,7 @@
 
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, policy.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, policy.Clone(), nullptr);
   handler.ApplyPolicySettings(policy_map, &prefs);
   EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
   EXPECT_EQ(expected, *value);
@@ -88,7 +88,7 @@
 
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, policy.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, policy.Clone(), nullptr);
   handler.ApplyPolicySettings(policy_map, &prefs);
   EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
   EXPECT_EQ(expected, *value);
@@ -96,7 +96,7 @@
   policy.AppendString("invalid Name");
   policy_map.Set(policy::key::kNativeMessagingBlacklist,
                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                 policy::POLICY_SOURCE_CLOUD, policy.CreateDeepCopy(), nullptr);
+                 policy::POLICY_SOURCE_CLOUD, policy.Clone(), nullptr);
   handler.ApplyPolicySettings(policy_map, &prefs);
   EXPECT_TRUE(prefs.GetValue(kTestPref, &value));
   EXPECT_EQ(expected, *value);
diff --git a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
index ca9cdc7..ee1e23a 100644
--- a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
@@ -59,16 +59,16 @@
 }
 
 void VerifyDestinationCompleted(
-    const NetworkingCastPrivateDelegate::VerifiedCallback& success_callback,
-    const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
+    NetworkingCastPrivateDelegate::VerifiedCallback success_callback,
+    NetworkingCastPrivateDelegate::FailureCallback failure_callback,
     VerificationResult result) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (result == VerificationResult::DECODE_FAILURE) {
-    failure_callback.Run(kErrorEncryptionError);
+    std::move(failure_callback).Run(kErrorEncryptionError);
     return;
   }
 
-  success_callback.Run(result == VerificationResult::SUCCESS);
+  std::move(success_callback).Run(result == VerificationResult::SUCCESS);
 }
 
 // Called from a blocking pool task runner. Returns |data| encoded using
@@ -103,14 +103,14 @@
 }
 
 void VerifyAndEncryptDataCompleted(
-    const NetworkingCastPrivateDelegate::DataCallback& success_callback,
-    const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
+    NetworkingCastPrivateDelegate::DataCallback success_callback,
+    NetworkingCastPrivateDelegate::FailureCallback failure_callback,
     const std::string& encrypted_data) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (encrypted_data.empty())
-    failure_callback.Run(kErrorEncryptionError);
+    std::move(failure_callback).Run(kErrorEncryptionError);
   else
-    success_callback.Run(encrypted_data);
+    std::move(success_callback).Run(encrypted_data);
 }
 
 }  // namespace
@@ -134,25 +134,25 @@
 
 void ChromeNetworkingCastPrivateDelegate::VerifyDestination(
     std::unique_ptr<Credentials> credentials,
-    const VerifiedCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VerifiedCallback success_callback,
+    FailureCallback failure_callback) {
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&RunDecodeAndVerifyCredentials, std::move(credentials)),
-      base::BindOnce(&VerifyDestinationCompleted, success_callback,
-                     failure_callback));
+      base::BindOnce(&VerifyDestinationCompleted, std::move(success_callback),
+                     std::move(failure_callback)));
 }
 
 void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptData(
     const std::string& data,
     std::unique_ptr<Credentials> credentials,
-    const DataCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    DataCallback success_callback,
+    FailureCallback failure_callback) {
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&RunVerifyAndEncryptData, data, std::move(credentials)),
-      base::BindOnce(&VerifyAndEncryptDataCompleted, success_callback,
-                     failure_callback));
+      base::BindOnce(&VerifyAndEncryptDataCompleted,
+                     std::move(success_callback), std::move(failure_callback)));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
index 9242d0d..0bfd51b 100644
--- a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
+++ b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
@@ -18,8 +18,8 @@
 class ChromeNetworkingCastPrivateDelegate
     : public NetworkingCastPrivateDelegate {
  public:
-  using FactoryCallback =
-      base::Callback<std::unique_ptr<ChromeNetworkingCastPrivateDelegate>()>;
+  using FactoryCallback = base::RepeatingCallback<
+      std::unique_ptr<ChromeNetworkingCastPrivateDelegate>()>;
   static void SetFactoryCallbackForTest(FactoryCallback* factory_callback);
 
   static std::unique_ptr<ChromeNetworkingCastPrivateDelegate> Create();
@@ -28,12 +28,12 @@
 
   // NetworkingCastPrivateDelegate overrides:
   void VerifyDestination(std::unique_ptr<Credentials> credentials,
-                         const VerifiedCallback& success_callback,
-                         const FailureCallback& failure_callback) override;
+                         VerifiedCallback success_callback,
+                         FailureCallback failure_callback) override;
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
-                            const DataCallback& success_callback,
-                            const FailureCallback& failure_callback) override;
+                            DataCallback success_callback,
+                            FailureCallback failure_callback) override;
 
  protected:
   ChromeNetworkingCastPrivateDelegate();
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
index f971b46..7c41f20 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
@@ -44,10 +44,10 @@
       ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
   delegate->VerifyDestination(
       AsCastCredentials(params->properties),
-      base::Bind(&NetworkingCastPrivateVerifyDestinationFunction::Success,
-                 this),
-      base::Bind(&NetworkingCastPrivateVerifyDestinationFunction::Failure,
-                 this));
+      base::BindOnce(&NetworkingCastPrivateVerifyDestinationFunction::Success,
+                     this),
+      base::BindOnce(&NetworkingCastPrivateVerifyDestinationFunction::Failure,
+                     this));
 
   // VerifyDestination might respond synchronously, e.g. in tests.
   return did_respond() ? AlreadyResponded() : RespondLater();
@@ -75,10 +75,10 @@
       ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
   delegate->VerifyAndEncryptData(
       params->data, AsCastCredentials(params->properties),
-      base::Bind(&NetworkingCastPrivateVerifyAndEncryptDataFunction::Success,
-                 this),
-      base::Bind(&NetworkingCastPrivateVerifyAndEncryptDataFunction::Failure,
-                 this));
+      base::BindOnce(
+          &NetworkingCastPrivateVerifyAndEncryptDataFunction::Success, this),
+      base::BindOnce(
+          &NetworkingCastPrivateVerifyAndEncryptDataFunction::Failure, this));
 
   // VerifyAndEncryptData might respond synchronously, e.g. in tests.
   return did_respond() ? AlreadyResponded() : RespondLater();
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
index 03cbc9b..0012c16 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
@@ -37,18 +37,18 @@
   ~TestNetworkingCastPrivateDelegate() override {}
 
   void VerifyDestination(std::unique_ptr<Credentials> credentials,
-                         const VerifiedCallback& success_callback,
-                         const FailureCallback& failure_callback) override {
+                         VerifiedCallback success_callback,
+                         FailureCallback failure_callback) override {
     AssertCredentials(*credentials);
-    success_callback.Run(true);
+    std::move(success_callback).Run(true);
   }
 
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
-                            const DataCallback& success_callback,
-                            const FailureCallback& failure_callback) override {
+                            DataCallback success_callback,
+                            FailureCallback failure_callback) override {
     AssertCredentials(*credentials);
-    success_callback.Run("encrypted_data");
+    std::move(success_callback).Run("encrypted_data");
   }
 
  private:
@@ -83,7 +83,7 @@
   }
 
   void SetUp() override {
-    networking_cast_private_delegate_factory_ = base::Bind(
+    networking_cast_private_delegate_factory_ = base::BindRepeating(
         &NetworkingCastPrivateApiTest::CreateNetworkingCastPrivateDelegate,
         base::Unretained(this));
     ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
index 4771cf6..046f687 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
@@ -60,41 +60,43 @@
   }
 
   void GetState(const std::string& guid,
-                const DictionaryCallback& success_callback,
-                const FailureCallback& failure_callback) override {
-    DictionaryResult(guid, success_callback, failure_callback);
+                DictionaryCallback success_callback,
+                FailureCallback failure_callback) override {
+    DictionaryResult(guid, std::move(success_callback),
+                     std::move(failure_callback));
   }
 
   void SetProperties(const std::string& guid,
                      std::unique_ptr<base::DictionaryValue> properties,
                      bool allow_set_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
   void CreateNetwork(bool shared,
                      std::unique_ptr<base::DictionaryValue> properties,
-                     const StringCallback& success_callback,
-                     const FailureCallback& failure_callback) override {
-    StringResult(success_callback, failure_callback, kSuccess);
+                     StringCallback success_callback,
+                     FailureCallback failure_callback) override {
+    StringResult(std::move(success_callback), std::move(failure_callback),
+                 kSuccess);
   }
 
   void ForgetNetwork(const std::string& guid,
                      bool allow_forget_shared_network,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
   void GetNetworks(const std::string& network_type,
                    bool configured_only,
                    bool visible_only,
                    int limit,
-                   const NetworkListCallback& success_callback,
-                   const FailureCallback& failure_callback) override {
+                   NetworkListCallback success_callback,
+                   FailureCallback failure_callback) override {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
       std::unique_ptr<base::ListValue> result(new base::ListValue);
       std::unique_ptr<base::DictionaryValue> network(new base::DictionaryValue);
@@ -102,59 +104,58 @@
                          ::onc::network_config::kEthernet);
       network->SetString(::onc::network_config::kGUID, kGuid);
       result->Append(std::move(network));
-      success_callback.Run(std::move(result));
+      std::move(success_callback).Run(std::move(result));
     }
   }
 
   void StartConnect(const std::string& guid,
-                    const VoidCallback& success_callback,
-                    const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                    VoidCallback success_callback,
+                    FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
   void StartDisconnect(const std::string& guid,
-                       const VoidCallback& success_callback,
-                       const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                       VoidCallback success_callback,
+                       FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
   void StartActivate(const std::string& guid,
                      const std::string& carrier,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
-  void GetCaptivePortalStatus(
-      const std::string& guid,
-      const StringCallback& success_callback,
-      const FailureCallback& failure_callback) override {
-    StringResult(success_callback, failure_callback, kOnline);
+  void GetCaptivePortalStatus(const std::string& guid,
+                              StringCallback success_callback,
+                              FailureCallback failure_callback) override {
+    StringResult(std::move(success_callback), std::move(failure_callback),
+                 kOnline);
   }
 
   void UnlockCellularSim(const std::string& guid,
                          const std::string& pin,
                          const std::string& puk,
-                         const VoidCallback& success_callback,
-                         const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                         VoidCallback success_callback,
+                         FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
   void SetCellularSimState(const std::string& guid,
                            bool require_pin,
                            const std::string& current_pin,
                            const std::string& new_pin,
-                           const VoidCallback& success_callback,
-                           const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+                           VoidCallback success_callback,
+                           FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
-  void SelectCellularMobileNetwork(
-      const std::string& guid,
-      const std::string& nework_id,
-      const VoidCallback& success_callback,
-      const FailureCallback& failure_callback) override {
-    VoidResult(success_callback, failure_callback);
+  void SelectCellularMobileNetwork(const std::string& guid,
+                                   const std::string& nework_id,
+                                   VoidCallback success_callback,
+                                   FailureCallback failure_callback) override {
+    VoidResult(std::move(success_callback), std::move(failure_callback));
   }
 
   // Synchronous methods
@@ -209,44 +210,44 @@
   const std::vector<std::string>& GetScanRequested() { return scan_requested_; }
 
   void DictionaryResult(const std::string& guid,
-                        const DictionaryCallback& success_callback,
-                        const FailureCallback& failure_callback) {
+                        DictionaryCallback success_callback,
+                        FailureCallback failure_callback) {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
       std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
       result->SetString(::onc::network_config::kGUID, guid);
       result->SetString(::onc::network_config::kType,
                         ::onc::network_config::kWiFi);
-      success_callback.Run(std::move(result));
+      std::move(success_callback).Run(std::move(result));
     }
   }
 
-  void StringResult(const StringCallback& success_callback,
-                    const FailureCallback& failure_callback,
+  void StringResult(StringCallback success_callback,
+                    FailureCallback failure_callback,
                     const std::string& result) {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
-      success_callback.Run(result);
+      std::move(success_callback).Run(result);
     }
   }
 
-  void BoolResult(const BoolCallback& success_callback,
-                  const FailureCallback& failure_callback) {
+  void BoolResult(BoolCallback success_callback,
+                  FailureCallback failure_callback) {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
-      success_callback.Run(true);
+      std::move(success_callback).Run(true);
     }
   }
 
-  void VoidResult(const VoidCallback& success_callback,
-                  const FailureCallback& failure_callback) {
+  void VoidResult(VoidCallback success_callback,
+                  FailureCallback failure_callback) {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
-      success_callback.Run();
+      std::move(success_callback).Run();
     }
   }
 
@@ -280,23 +281,23 @@
   ~TestNetworkingCastPrivateDelegate() override {}
 
   void VerifyDestination(std::unique_ptr<Credentials> credentials,
-                         const VerifiedCallback& success_callback,
-                         const FailureCallback& failure_callback) override {
+                         VerifiedCallback success_callback,
+                         FailureCallback failure_callback) override {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
-      success_callback.Run(true);
+      std::move(success_callback).Run(true);
     }
   }
 
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
-                            const DataCallback& success_callback,
-                            const FailureCallback& failure_callback) override {
+                            DataCallback success_callback,
+                            FailureCallback failure_callback) override {
     if (fail_) {
-      failure_callback.Run(kFailure);
+      std::move(failure_callback).Run(kFailure);
     } else {
-      success_callback.Run("encrypted_data");
+      std::move(success_callback).Run("encrypted_data");
     }
   }
 
@@ -312,7 +313,7 @@
   ~NetworkingPrivateApiTest() override = default;
 
   void SetUp() override {
-    networking_cast_delegate_factory_ = base::Bind(
+    networking_cast_delegate_factory_ = base::BindRepeating(
         &NetworkingPrivateApiTest::CreateTestNetworkingCastPrivateDelegate,
         base::Unretained(this), test_failure_);
     ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 349d244..09665fa 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -115,18 +115,18 @@
 
   // VerifyDelegate
   void VerifyDestination(std::unique_ptr<Credentials> credentials,
-                         const VerifiedCallback& success_callback,
-                         const FailureCallback& failure_callback) override {
+                         VerifiedCallback success_callback,
+                         FailureCallback failure_callback) override {
     AssertCredentials(*credentials);
-    success_callback.Run(true);
+    std::move(success_callback).Run(true);
   }
 
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
-                            const DataCallback& success_callback,
-                            const FailureCallback& failure_callback) override {
+                            DataCallback success_callback,
+                            FailureCallback failure_callback) override {
     AssertCredentials(*credentials);
-    success_callback.Run("encrypted_data");
+    std::move(success_callback).Run("encrypted_data");
   }
 
  private:
@@ -335,7 +335,7 @@
   }
 
   void SetUp() override {
-    networking_cast_delegate_factory_ = base::Bind(
+    networking_cast_delegate_factory_ = base::BindRepeating(
         &NetworkingPrivateChromeOSApiTest::CreateNetworkingCastPrivateDelegate,
         base::Unretained(this));
     ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
@@ -848,8 +848,9 @@
 
   TestListener listener(
       "notifyPortalDetectorObservers",
-      base::Bind(&NetworkPortalDetectorTestImpl::NotifyObserversForTesting,
-                 base::Unretained(detector())));
+      base::BindRepeating(
+          &NetworkPortalDetectorTestImpl::NotifyObserversForTesting,
+          base::Unretained(detector())));
   EXPECT_TRUE(RunNetworkingSubtest("captivePortalNotification")) << message_;
 }
 
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
index db6d82e3..6ee0259 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
@@ -52,18 +52,18 @@
   ~TestNetworkingCastPrivateDelegate() override = default;
 
   void VerifyDestination(std::unique_ptr<Credentials> credentials,
-                         const VerifiedCallback& success_callback,
-                         const FailureCallback& failure_callback) override {
+                         VerifiedCallback success_callback,
+                         FailureCallback failure_callback) override {
     AssertCredentials(*credentials);
-    success_callback.Run(true);
+    std::move(success_callback).Run(true);
   }
 
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
-                            const DataCallback& success_callback,
-                            const FailureCallback& failure_callback) override {
+                            DataCallback success_callback,
+                            FailureCallback failure_callback) override {
     AssertCredentials(*credentials);
-    success_callback.Run("encrypted_data");
+    std::move(success_callback).Run("encrypted_data");
   }
 
  private:
@@ -111,9 +111,9 @@
 
   void SetUp() override {
     networking_cast_delegate_factory_ =
-        base::Bind(&NetworkingPrivateServiceClientApiTest::
-                       CreateNetworkingCastPrivateDelegate,
-                   base::Unretained(this));
+        base::BindRepeating(&NetworkingPrivateServiceClientApiTest::
+                                CreateNetworkingCastPrivateDelegate,
+                            base::Unretained(this));
     ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
         &networking_cast_delegate_factory_);
     extensions::ExtensionApiTest::SetUp();
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index f9af7ae..a29ca47 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -118,9 +118,12 @@
   // System timezone is never directly changeable by the user.
   if (pref_name == chromeos::kSystemTimezone)
     return chromeos::system::PerUserTimezoneEnabled();
-  // enable_screen_lock must be changed through the quickUnlockPrivate API.
-  if (pref_name == ash::prefs::kEnableAutoScreenLock)
+  // enable_screen_lock and pin_unlock_autosubmit_enabled
+  // must be changed through the quickUnlockPrivate API.
+  if (pref_name == ash::prefs::kEnableAutoScreenLock ||
+      pref_name == prefs::kPinUnlockAutosubmitEnabled) {
     return true;
+  }
 #endif
 #if defined(OS_WIN)
   // Don't allow user to change sw_reporter preferences.
@@ -400,6 +403,9 @@
   // kEnableAutoScreenLock is read-only.
   (*s_whitelist)[ash::prefs::kEnableAutoScreenLock] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
+  // kPinUnlockAutosubmitEnabled is read-only.
+  (*s_whitelist)[prefs::kPinUnlockAutosubmitEnabled] =
+      settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_whitelist)[ash::prefs::kMessageCenterLockScreenMode] =
       settings_api::PrefType::PREF_TYPE_STRING;
 
diff --git a/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc b/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
index 0da80d2..c7be0966 100644
--- a/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
+++ b/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
@@ -137,10 +137,10 @@
   base::Value expected(123);
   policies.Set("must", policy::POLICY_LEVEL_MANDATORY,
                policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-               expected.CreateDeepCopy(), nullptr);
+               expected.Clone(), nullptr);
   policies.Set("may", policy::POLICY_LEVEL_RECOMMENDED,
                policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(456), nullptr);
+               base::Value(456), nullptr);
   SetCurrentPolicy(policies);
 
   ValueStore::ReadResult result = store_->Get();
@@ -183,7 +183,7 @@
 
   policy::PolicyMap policies;
   policies.Set("aaa", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-               policy::POLICY_SOURCE_CLOUD, value.CreateDeepCopy(), nullptr);
+               policy::POLICY_SOURCE_CLOUD, value.Clone(), nullptr);
   SetCurrentPolicy(policies);
   Mock::VerifyAndClearExpectations(&observer_);
 
@@ -198,7 +198,7 @@
   }
 
   policies.Set("bbb", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-               policy::POLICY_SOURCE_CLOUD, value.CreateDeepCopy(), nullptr);
+               policy::POLICY_SOURCE_CLOUD, value.Clone(), nullptr);
   SetCurrentPolicy(policies);
   Mock::VerifyAndClearExpectations(&observer_);
 
@@ -215,8 +215,7 @@
   }
 
   policies.Set("bbb", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-               policy::POLICY_SOURCE_CLOUD, new_value.CreateDeepCopy(),
-               nullptr);
+               policy::POLICY_SOURCE_CLOUD, new_value.Clone(), nullptr);
   SetCurrentPolicy(policies);
   Mock::VerifyAndClearExpectations(&observer_);
 
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index 81c069ec..6f43a41f 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -7,6 +7,8 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/extensions/chrome_extension_browser_constants.h"
@@ -580,6 +582,8 @@
   if (!web_contents)
     return;
 
+  LogPageAccessAction(command_id);
+
   if (command_id == PAGE_ACCESS_LEARN_MORE) {
     content::OpenURLParams params(
         GURL(chrome_extension_constants::kRuntimeHostPermissionsHelpURL),
@@ -614,6 +618,30 @@
                                      convert_page_access(command_id));
 }
 
+void ExtensionContextMenuModel::LogPageAccessAction(int command_id) const {
+  switch (command_id) {
+    case PAGE_ACCESS_LEARN_MORE:
+      base::RecordAction(base::UserMetricsAction(
+          "Extensions.ContextMenu.Hosts.LearnMoreClicked"));
+      break;
+    case PAGE_ACCESS_RUN_ON_CLICK:
+      base::RecordAction(base::UserMetricsAction(
+          "Extensions.ContextMenu.Hosts.OnClickClicked"));
+      break;
+    case PAGE_ACCESS_RUN_ON_SITE:
+      base::RecordAction(base::UserMetricsAction(
+          "Extensions.ContextMenu.Hosts.OnSiteClicked"));
+      break;
+    case PAGE_ACCESS_RUN_ON_ALL_SITES:
+      base::RecordAction(base::UserMetricsAction(
+          "Extensions.ContextMenu.Hosts.OnAllSitesClicked"));
+      break;
+    default:
+      NOTREACHED() << "Unknown option: " << command_id;
+      break;
+  }
+}
+
 content::WebContents* ExtensionContextMenuModel::GetActiveWebContents() const {
   return browser_->tab_strip_model()->GetActiveWebContents();
 }
diff --git a/chrome/browser/extensions/extension_context_menu_model.h b/chrome/browser/extensions/extension_context_menu_model.h
index 3fe44143..06b90af 100644
--- a/chrome/browser/extensions/extension_context_menu_model.h
+++ b/chrome/browser/extensions/extension_context_menu_model.h
@@ -131,6 +131,10 @@
   void HandlePageAccessCommand(int command_id,
                                const Extension* extension) const;
 
+  // Logs a user action when an option is selected in the page access section of
+  // the context menu.
+  void LogPageAccessAction(int command_id) const;
+
   // Gets the extension we are displaying the menu for. Returns NULL if the
   // extension has been uninstalled and no longer exists.
   const Extension* GetExtension() const;
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
index 067a4a30..62fc694 100644
--- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc
+++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/metrics/user_action_tester.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/extensions/chrome_extension_browser_constants.h"
 #include "chrome/browser/extensions/context_menu_matcher.h"
@@ -652,6 +653,13 @@
 }
 
 TEST_F(ExtensionContextMenuModelTest, TestPageAccessSubmenu) {
+  base::UserActionTester user_action_tester;
+  constexpr char kOnClickAction[] =
+      "Extensions.ContextMenu.Hosts.OnClickClicked";
+  constexpr char kOnSiteAction[] = "Extensions.ContextMenu.Hosts.OnSiteClicked";
+  constexpr char kOnAllSitesAction[] =
+      "Extensions.ContextMenu.Hosts.OnAllSitesClicked";
+
   InitializeEmptyExtensionService();
 
   // Add an extension with all urls, and withhold permission.
@@ -707,11 +715,18 @@
   const PermissionsData* permissions = extension->permissions_data();
   EXPECT_FALSE(permissions->withheld_permissions().IsEmpty());
 
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kOnClickAction));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kOnSiteAction));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kOnAllSitesAction));
+
   // Change the mode to be "Run on site".
   menu.ExecuteCommand(kRunOnSite, 0);
   EXPECT_FALSE(menu.IsCommandIdChecked(kRunOnClick));
   EXPECT_TRUE(menu.IsCommandIdChecked(kRunOnSite));
   EXPECT_FALSE(menu.IsCommandIdChecked(kRunOnAllSites));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kOnClickAction));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kOnSiteAction));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kOnAllSitesAction));
 
   // The extension should have access to the active url, but not to another
   // arbitrary url, and the extension should still have withheld permissions.
@@ -746,6 +761,9 @@
   EXPECT_FALSE(menu.IsCommandIdChecked(kRunOnClick));
   EXPECT_FALSE(menu.IsCommandIdChecked(kRunOnSite));
   EXPECT_TRUE(menu.IsCommandIdChecked(kRunOnAllSites));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kOnClickAction));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kOnSiteAction));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kOnAllSitesAction));
 
   // The extension should be able to run on any url, and shouldn't have any
   // withheld permissions.
@@ -776,6 +794,9 @@
   EXPECT_TRUE(menu.IsCommandIdChecked(kRunOnClick));
   EXPECT_FALSE(menu.IsCommandIdChecked(kRunOnSite));
   EXPECT_FALSE(menu.IsCommandIdChecked(kRunOnAllSites));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kOnClickAction));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kOnSiteAction));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kOnAllSitesAction));
 
   // We should return to the initial state - no access.
   EXPECT_FALSE(permissions_modifier.HasGrantedHostPermission(kActiveUrl));
@@ -1412,6 +1433,9 @@
 }
 
 TEST_F(ExtensionContextMenuModelTest, TestClickingPageAccessLearnMore) {
+  base::UserActionTester user_action_tester;
+  constexpr char kLearnMoreAction[] =
+      "Extensions.ContextMenu.Hosts.LearnMoreClicked";
   InitializeEmptyExtensionService();
 
   // Add an extension that wants access to a.com.
@@ -1429,6 +1453,7 @@
   ExtensionContextMenuModel menu(extension.get(), browser,
                                  ExtensionContextMenuModel::VISIBLE, nullptr,
                                  true);
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kLearnMoreAction));
 
   const ExtensionContextMenuModel::MenuEntries kLearnMore =
       ExtensionContextMenuModel::PAGE_ACCESS_LEARN_MORE;
@@ -1439,6 +1464,7 @@
   EXPECT_EQ(2, browser->tab_strip_model()->count());
   content::WebContents* web_contents =
       browser->tab_strip_model()->GetActiveWebContents();
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kLearnMoreAction));
 
   // Test web contents need a poke to commit.
   content::NavigationController& controller = web_contents->GetController();
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc b/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc
index 26f9c18d7..301175d 100644
--- a/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc
+++ b/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc
@@ -164,7 +164,19 @@
   base::UmaHistogramCounts100("Extensions.ForceInstalledTotalCandidateCount",
                               tracker_->extensions().size());
   std::set<ExtensionId> missing_forced_extensions;
+  InstallStageTracker* install_stage_tracker =
+      InstallStageTracker::Get(profile_);
   for (const auto& extension : tracker_->extensions()) {
+    InstallStageTracker::InstallationData installation =
+        install_stage_tracker->Get(extension.first);
+    if (installation.download_manifest_finish_time) {
+      DCHECK(installation.download_manifest_started_time);
+      base::UmaHistogramLongTimes(
+          "Extensions.ForceInstalledTime.DownloadingStartTo."
+          "ManifestDownloadComplete",
+          installation.download_manifest_finish_time.value() -
+              installation.download_manifest_started_time.value());
+    }
     if (!IsStatusGood(extension.second.status))
       missing_forced_extensions.insert(extension.first);
   }
@@ -176,8 +188,6 @@
     VLOG(2) << "All forced extensions seems to be installed";
     return;
   }
-  InstallStageTracker* install_stage_tracker =
-      InstallStageTracker::Get(profile_);
   size_t enabled_missing_count = missing_forced_extensions.size();
   size_t blocklisted_count = 0;
   auto installed_extensions = registry_->GenerateInstalledExtensionsSet();
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc
index 3c83731..4fe43e3 100644
--- a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc
+++ b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc
@@ -106,6 +106,8 @@
     "Extensions.ForceInstalledFailureNoUpdatesInfo";
 constexpr char kExtensionManifestInvalidAppStatusError[] =
     "Extensions.ForceInstalledFailureManifestInvalidAppStatusError";
+constexpr char kManifestDownloadTimeStats[] =
+    "Extensions.ForceInstalledTime.DownloadingStartTo.ManifestDownloadComplete";
 }  // namespace
 
 namespace extensions {
@@ -187,6 +189,19 @@
     base::RunLoop().RunUntilIdle();
   }
 
+  // Report downloading manifest stage for both the extensions.
+  void ReportDownloadingManifestStage() {
+    auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build();
+    install_stage_tracker_->ReportDownloadingStage(
+        kExtensionId1,
+        ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
+    tracker_->OnExtensionLoaded(profile_, ext1.get());
+    auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build();
+    install_stage_tracker_->ReportDownloadingStage(
+        kExtensionId2,
+        ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
+  }
+
   // ForceInstalledTracker::Observer overrides:
   void OnForceInstalledExtensionsLoaded() override { loaded_call_count_++; }
   void OnForceInstalledExtensionsReady() override { ready_call_count_++; }
@@ -301,6 +316,19 @@
       prefs_->GetManagedPref(pref_names::kInstallForceList)->DictSize(), 1);
 }
 
+TEST_F(ForceInstalledMetricsTest, ExtensionsManifestDownloadTime) {
+  SetupForceList();
+  ReportDownloadingManifestStage();
+  install_stage_tracker_->ReportDownloadingStage(
+      kExtensionId1, ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED);
+  install_stage_tracker_->ReportFailure(
+      kExtensionId2, InstallStageTracker::FailureReason::MANIFEST_INVALID);
+  // ForceInstalledMetrics shuts down timer because all extension are either
+  // loaded or failed.
+  EXPECT_FALSE(fake_timer_->IsRunning());
+  histogram_tester_.ExpectTotalCount(kManifestDownloadTimeStats, 1);
+}
+
 // Reporting disable reason for the force installed extensions which are
 // installed but not loaded when extension is disable due to single reason.
 TEST_F(ForceInstalledMetricsTest,
diff --git a/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc b/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc
index 39918b2..d783a7b 100644
--- a/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc
+++ b/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc
@@ -143,6 +143,10 @@
     ExtensionDownloaderDelegate::Stage stage) {
   InstallationData& data = installation_data_map_[id];
   data.downloading_stage = stage;
+  if (stage == ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST)
+    data.download_manifest_started_time = base::Time::Now();
+  else if (stage == ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED)
+    data.download_manifest_finish_time = base::Time::Now();
   for (auto& observer : observers_) {
     observer.OnExtensionDataChangedForTesting(id, browser_context_, data);
   }
diff --git a/chrome/browser/extensions/forced_extensions/install_stage_tracker.h b/chrome/browser/extensions/forced_extensions/install_stage_tracker.h
index 630456d..08922be 100644
--- a/chrome/browser/extensions/forced_extensions/install_stage_tracker.h
+++ b/chrome/browser/extensions/forced_extensions/install_stage_tracker.h
@@ -290,6 +290,11 @@
     // Type of app status error received from update server when manifest was
     // fetched.
     base::Optional<AppStatusError> app_status_error;
+    // Time at which the download is started.
+    base::Optional<base::Time> download_manifest_started_time;
+    // Time at which the update manifest is downloaded and successfully parsed
+    // from the server.
+    base::Optional<base::Time> download_manifest_finish_time;
   };
 
   class Observer : public base::CheckedObserver {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c3b0dcf..d723c48 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3135,7 +3135,7 @@
   {
     "name": "omnibox-assistant-voice-search",
     "owners": [ "wylieb", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 85
+    "expiry_milestone": 88
   },
   {
     "name": "omnibox-autocomplete-titles",
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 1f07cd2..221717b 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -219,7 +219,6 @@
     &features::kDnsOverHttps,
     &net::features::kSameSiteByDefaultCookies,
     &net::features::kCookiesWithoutSameSiteMustBeSecure,
-    &paint_preview::kPaintPreviewCaptureExperiment,
     &paint_preview::kPaintPreviewDemo,
     &paint_preview::kPaintPreviewShowOnStartup,
     &permissions::features::kPermissionDelegation,
@@ -256,6 +255,7 @@
     &safe_browsing::kSafeBrowsingSecuritySectionUIAndroid,
     &security_state::features::kMarkHttpAsFeature,
     &signin::kMobileIdentityConsistency,
+    &switches::kDecoupleSyncFromAndroidMasterSync,
     &switches::kSyncUseSessionsUnregisterDelay,
     &subresource_filter::kSafeBrowsingSubresourceFilter,
 };
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 8bb8d59..d3b00cf 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
@@ -271,6 +271,8 @@
             "CookiesWithoutSameSiteMustBeSecure";
     public static final String DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING =
             "DarkenWebsitesCheckboxInThemesSetting";
+    public static final String DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC =
+            "DecoupleSyncFromAndroidMasterSync";
     public static final String DIRECT_ACTIONS = "DirectActions";
     public static final String DNS_OVER_HTTPS = "DnsOverHttps";
     public static final String DOWNLOAD_FILE_PROVIDER = "DownloadFileProvider";
@@ -344,7 +346,6 @@
     public static final String OVERLAY_NEW_LAYOUT = "OverlayNewLayout";
     public static final String OVERSCROLL_HISTORY_NAVIGATION = "OverscrollHistoryNavigation";
     public static final String PAGE_INFO_PERFORMANCE_HINTS = "PageInfoPerformanceHints";
-    public static final String PAINT_PREVIEW_CAPTURE_EXPERIMENT = "PaintPreviewCaptureExperiment";
     public static final String PAINT_PREVIEW_DEMO = "PaintPreviewDemo";
     public static final String PAINT_PREVIEW_SHOW_ON_STARTUP = "PaintPreviewShowOnStartup";
     public static final String PASSWORD_CHECK = "PasswordCheck";
diff --git a/chrome/browser/nearby_sharing/client/BUILD.gn b/chrome/browser/nearby_sharing/client/BUILD.gn
new file mode 100644
index 0000000..395d426
--- /dev/null
+++ b/chrome/browser/nearby_sharing/client/BUILD.gn
@@ -0,0 +1,66 @@
+# 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.
+
+source_set("client") {
+  sources = [
+    "nearby_share_api_call_flow.h",
+    "nearby_share_api_call_flow_impl.cc",
+    "nearby_share_api_call_flow_impl.h",
+    "nearby_share_client.h",
+    "nearby_share_client_impl.cc",
+    "nearby_share_client_impl.h",
+    "nearby_share_request_error.cc",
+    "nearby_share_request_error.h",
+    "nearby_share_switches.cc",
+    "nearby_share_switches.h",
+  ]
+
+  deps = [
+    "//base",
+    "//chrome/browser/nearby_sharing/logging",
+    "//chrome/browser/nearby_sharing/proto",
+    "//components/signin/public/identity_manager",
+    "//net",
+    "//net/traffic_annotation",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
+    "//url",
+  ]
+}
+
+source_set("test_support") {
+  testonly = true
+
+  sources = [
+    "fake_nearby_share_client.cc",
+    "fake_nearby_share_client.h",
+  ]
+
+  deps = [
+    ":client",
+    "//base",
+    "//chrome/browser/nearby_sharing/proto",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [
+    "nearby_share_api_call_flow_impl_unittest.cc",
+    "nearby_share_client_impl_unittest.cc",
+  ]
+
+  deps = [
+    ":client",
+    "//base",
+    "//base/test:test_support",
+    "//chrome/browser/nearby_sharing/proto",
+    "//components/signin/public/identity_manager:test_support",
+    "//net",
+    "//net/traffic_annotation:test_support",
+    "//services/network:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/browser/nearby_sharing/client/fake_nearby_share_client.cc b/chrome/browser/nearby_sharing/client/fake_nearby_share_client.cc
new file mode 100644
index 0000000..4128167
--- /dev/null
+++ b/chrome/browser/nearby_sharing/client/fake_nearby_share_client.cc
@@ -0,0 +1,124 @@
+// 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/nearby_sharing/client/fake_nearby_share_client.h"
+
+#include <utility>
+
+FakeNearbyShareClient::UpdateDeviceRequest::UpdateDeviceRequest(
+    const nearbyshare::proto::UpdateDeviceRequest& request,
+    UpdateDeviceCallback&& callback,
+    ErrorCallback&& error_callback)
+    : request(request),
+      callback(std::move(callback)),
+      error_callback(std::move(error_callback)) {}
+
+FakeNearbyShareClient::UpdateDeviceRequest::UpdateDeviceRequest(
+    FakeNearbyShareClient::UpdateDeviceRequest&& request) = default;
+
+FakeNearbyShareClient::UpdateDeviceRequest::~UpdateDeviceRequest() = default;
+
+FakeNearbyShareClient::CheckContactsReachabilityRequest::
+    CheckContactsReachabilityRequest(
+        const nearbyshare::proto::CheckContactsReachabilityRequest& request,
+        CheckContactsReachabilityCallback&& callback,
+        ErrorCallback&& error_callback)
+    : request(request),
+      callback(std::move(callback)),
+      error_callback(std::move(error_callback)) {}
+
+FakeNearbyShareClient::CheckContactsReachabilityRequest::
+    CheckContactsReachabilityRequest(
+        FakeNearbyShareClient::CheckContactsReachabilityRequest&& request) =
+        default;
+
+FakeNearbyShareClient::CheckContactsReachabilityRequest::
+    ~CheckContactsReachabilityRequest() = default;
+
+FakeNearbyShareClient::ListContactPeopleRequest::ListContactPeopleRequest(
+    const nearbyshare::proto::ListContactPeopleRequest& request,
+    ListContactPeopleCallback&& callback,
+    ErrorCallback&& error_callback)
+    : request(request),
+      callback(std::move(callback)),
+      error_callback(std::move(error_callback)) {}
+
+FakeNearbyShareClient::ListContactPeopleRequest::ListContactPeopleRequest(
+    FakeNearbyShareClient::ListContactPeopleRequest&& request) = default;
+
+FakeNearbyShareClient::ListContactPeopleRequest::~ListContactPeopleRequest() =
+    default;
+
+FakeNearbyShareClient::ListPublicCertificatesRequest::
+    ListPublicCertificatesRequest(
+        const nearbyshare::proto::ListPublicCertificatesRequest& request,
+        ListPublicCertificatesCallback&& callback,
+        ErrorCallback&& error_callback)
+    : request(request),
+      callback(std::move(callback)),
+      error_callback(std::move(error_callback)) {}
+
+FakeNearbyShareClient::ListPublicCertificatesRequest::
+    ListPublicCertificatesRequest(
+        FakeNearbyShareClient::ListPublicCertificatesRequest&& request) =
+        default;
+
+FakeNearbyShareClient::ListPublicCertificatesRequest::
+    ~ListPublicCertificatesRequest() = default;
+
+FakeNearbyShareClient::FakeNearbyShareClient() = default;
+
+FakeNearbyShareClient::~FakeNearbyShareClient() = default;
+
+void FakeNearbyShareClient::SetAccessTokenUsed(const std::string& token) {
+  access_token_used_ = token;
+}
+
+void FakeNearbyShareClient::UpdateDevice(
+    const nearbyshare::proto::UpdateDeviceRequest& request,
+    UpdateDeviceCallback&& callback,
+    ErrorCallback&& error_callback) {
+  update_device_requests_.emplace_back(request, std::move(callback),
+                                       std::move(error_callback));
+}
+
+void FakeNearbyShareClient::CheckContactsReachability(
+    const nearbyshare::proto::CheckContactsReachabilityRequest& request,
+    CheckContactsReachabilityCallback&& callback,
+    ErrorCallback&& error_callback) {
+  check_contacts_reachabilty_requests_.emplace_back(
+      request, std::move(callback), std::move(error_callback));
+}
+
+void FakeNearbyShareClient::ListContactPeople(
+    const nearbyshare::proto::ListContactPeopleRequest& request,
+    ListContactPeopleCallback&& callback,
+    ErrorCallback&& error_callback) {
+  list_contact_people_requests_.emplace_back(request, std::move(callback),
+                                             std::move(error_callback));
+}
+
+void FakeNearbyShareClient::ListPublicCertificates(
+    const nearbyshare::proto::ListPublicCertificatesRequest& request,
+    ListPublicCertificatesCallback&& callback,
+    ErrorCallback&& error_callback) {
+  list_public_certificates_requests_.emplace_back(request, std::move(callback),
+                                                  std::move(error_callback));
+}
+
+std::string FakeNearbyShareClient::GetAccessTokenUsed() {
+  return access_token_used_;
+}
+
+FakeNearbyShareClientFactory::FakeNearbyShareClientFactory() = default;
+
+FakeNearbyShareClientFactory::~FakeNearbyShareClientFactory() = default;
+
+std::unique_ptr<NearbyShareClient>
+FakeNearbyShareClientFactory::CreateInstance() {
+  auto instance = std::make_unique<FakeNearbyShareClient>();
+  instances_.push_back(instance.get());
+
+  return instance;
+}
diff --git a/chrome/browser/nearby_sharing/client/fake_nearby_share_client.h b/chrome/browser/nearby_sharing/client/fake_nearby_share_client.h
new file mode 100644
index 0000000..f31ee3c
--- /dev/null
+++ b/chrome/browser/nearby_sharing/client/fake_nearby_share_client.h
@@ -0,0 +1,129 @@
+// 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_NEARBY_SHARING_CLIENT_FAKE_NEARBY_SHARE_CLIENT_H_
+#define CHROME_BROWSER_NEARBY_SHARING_CLIENT_FAKE_NEARBY_SHARE_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "chrome/browser/nearby_sharing/client/nearby_share_client.h"
+#include "chrome/browser/nearby_sharing/proto/certificate_rpc.pb.h"
+#include "chrome/browser/nearby_sharing/proto/contact_rpc.pb.h"
+#include "chrome/browser/nearby_sharing/proto/device_rpc.pb.h"
+
+// A fake implementation of the Nearby Share HTTP client that stores all request
+// data. Only use in unit tests.
+class FakeNearbyShareClient : public NearbyShareClient {
+ public:
+  struct UpdateDeviceRequest {
+    UpdateDeviceRequest(const nearbyshare::proto::UpdateDeviceRequest& request,
+                        UpdateDeviceCallback&& callback,
+                        ErrorCallback&& error_callback);
+    UpdateDeviceRequest(UpdateDeviceRequest&& request);
+    ~UpdateDeviceRequest();
+    nearbyshare::proto::UpdateDeviceRequest request;
+    UpdateDeviceCallback callback;
+    ErrorCallback error_callback;
+  };
+  struct CheckContactsReachabilityRequest {
+    CheckContactsReachabilityRequest(
+        const nearbyshare::proto::CheckContactsReachabilityRequest& request,
+        CheckContactsReachabilityCallback&& callback,
+        ErrorCallback&& error_callback);
+    CheckContactsReachabilityRequest(
+        CheckContactsReachabilityRequest&& request);
+    ~CheckContactsReachabilityRequest();
+    nearbyshare::proto::CheckContactsReachabilityRequest request;
+    CheckContactsReachabilityCallback callback;
+    ErrorCallback error_callback;
+  };
+  struct ListContactPeopleRequest {
+    ListContactPeopleRequest(
+        const nearbyshare::proto::ListContactPeopleRequest& request,
+        ListContactPeopleCallback&& callback,
+        ErrorCallback&& error_callback);
+    ListContactPeopleRequest(ListContactPeopleRequest&& request);
+    ~ListContactPeopleRequest();
+    nearbyshare::proto::ListContactPeopleRequest request;
+    ListContactPeopleCallback callback;
+    ErrorCallback error_callback;
+  };
+  struct ListPublicCertificatesRequest {
+    ListPublicCertificatesRequest(
+        const nearbyshare::proto::ListPublicCertificatesRequest& request,
+        ListPublicCertificatesCallback&& callback,
+        ErrorCallback&& error_callback);
+    ListPublicCertificatesRequest(ListPublicCertificatesRequest&& request);
+    ~ListPublicCertificatesRequest();
+    nearbyshare::proto::ListPublicCertificatesRequest request;
+    ListPublicCertificatesCallback callback;
+    ErrorCallback error_callback;
+  };
+
+  FakeNearbyShareClient();
+  ~FakeNearbyShareClient() override;
+
+  std::vector<UpdateDeviceRequest>& update_device_requests() {
+    return update_device_requests_;
+  }
+  std::vector<CheckContactsReachabilityRequest>&
+  check_contacts_reachabilty_requests() {
+    return check_contacts_reachabilty_requests_;
+  }
+  std::vector<ListContactPeopleRequest>& list_contact_people_requests() {
+    return list_contact_people_requests_;
+  }
+  std::vector<ListPublicCertificatesRequest>&
+  list_public_certificates_requests() {
+    return list_public_certificates_requests_;
+  }
+
+  void SetAccessTokenUsed(const std::string& token);
+
+ private:
+  // NearbyShareClient:
+  void UpdateDevice(const nearbyshare::proto::UpdateDeviceRequest& request,
+                    UpdateDeviceCallback&& callback,
+                    ErrorCallback&& error_callback) override;
+  void CheckContactsReachability(
+      const nearbyshare::proto::CheckContactsReachabilityRequest& request,
+      CheckContactsReachabilityCallback&& callback,
+      ErrorCallback&& error_callback) override;
+  void ListContactPeople(
+      const nearbyshare::proto::ListContactPeopleRequest& request,
+      ListContactPeopleCallback&& callback,
+      ErrorCallback&& error_callback) override;
+  void ListPublicCertificates(
+      const nearbyshare::proto::ListPublicCertificatesRequest& request,
+      ListPublicCertificatesCallback&& callback,
+      ErrorCallback&& error_callback) override;
+  std::string GetAccessTokenUsed() override;
+
+  std::vector<UpdateDeviceRequest> update_device_requests_;
+  std::vector<CheckContactsReachabilityRequest>
+      check_contacts_reachabilty_requests_;
+  std::vector<ListContactPeopleRequest> list_contact_people_requests_;
+  std::vector<ListPublicCertificatesRequest> list_public_certificates_requests_;
+  std::string access_token_used_;
+};
+
+class FakeNearbyShareClientFactory : public NearbyShareClientFactory {
+ public:
+  FakeNearbyShareClientFactory();
+  ~FakeNearbyShareClientFactory();
+
+ public:
+  // Returns all FakeNearbyShareClient instances created by CreateInstance().
+  std::vector<FakeNearbyShareClient*>& instances() { return instances_; }
+
+ private:
+  // NearbyShareClientFactory:
+  std::unique_ptr<NearbyShareClient> CreateInstance() override;
+
+  std::vector<FakeNearbyShareClient*> instances_;
+};
+
+#endif  // CHROME_BROWSER_NEARBY_SHARING_CLIENT_FAKE_NEARBY_SHARE_CLIENT_H_
diff --git a/chrome/browser/nearby_sharing/client/nearby_share_client.h b/chrome/browser/nearby_sharing/client/nearby_share_client.h
index f0c6352..8bdf7c8 100644
--- a/chrome/browser/nearby_sharing/client/nearby_share_client.h
+++ b/chrome/browser/nearby_sharing/client/nearby_share_client.h
@@ -10,7 +10,6 @@
 
 #include "base/callback_forward.h"
 #include "chrome/browser/nearby_sharing/client/nearby_share_request_error.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace nearbyshare {
 namespace proto {
@@ -48,33 +47,25 @@
   virtual void UpdateDevice(
       const nearbyshare::proto::UpdateDeviceRequest& request,
       UpdateDeviceCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag&
-          partial_traffic_annotation) = 0;
+      ErrorCallback&& error_callback) = 0;
 
   // NearbyShareService v1: CheckContactsReachability
   virtual void CheckContactsReachability(
       const nearbyshare::proto::CheckContactsReachabilityRequest& request,
       CheckContactsReachabilityCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag&
-          partial_traffic_annotation) = 0;
+      ErrorCallback&& error_callback) = 0;
 
   // NearbyShareService v1: ListContactPeople
   virtual void ListContactPeople(
       const nearbyshare::proto::ListContactPeopleRequest& request,
       ListContactPeopleCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag&
-          partial_traffic_annotation) = 0;
+      ErrorCallback&& error_callback) = 0;
 
   // NearbyShareService v1: ListPublicCertificates
   virtual void ListPublicCertificates(
       const nearbyshare::proto::ListPublicCertificatesRequest& request,
       ListPublicCertificatesCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag&
-          partial_traffic_annotation) = 0;
+      ErrorCallback&& error_callback) = 0;
 
   // Returns the access token used to make the request. If no request has been
   // made yet, this function will return an empty string.
diff --git a/chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc b/chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc
index 21da5d6..72657bb4 100644
--- a/chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc
+++ b/chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/nearby_sharing/client/nearby_share_api_call_flow_impl.h"
 #include "chrome/browser/nearby_sharing/client/nearby_share_switches.h"
@@ -87,6 +88,131 @@
   return query_parameters;
 }
 
+// TODO(crbug.com/1103471): Update "chrome_policy" when a Nearby Share
+// enterprise policy is created.
+const net::PartialNetworkTrafficAnnotationTag& GetUpdateDeviceAnnotation() {
+  static const base::NoDestructor<net::PartialNetworkTrafficAnnotationTag>
+      annotation(net::DefinePartialNetworkTrafficAnnotation(
+          "nearby_share_update_device", "oauth2_api_call_flow",
+          R"(
+      semantics {
+        sender: "Nearby Share"
+        description:
+          "Used as part of the Nearby Share feature that allows users to "
+          "share files or text with trusted contacts within a certain physical "
+          "proximity. The call sends the local device's user-defined name and "
+          "their list of allowed contacts to the Google-owned Nearby server. "
+          "Nearby-Share-specific crypto data from the local device is also "
+          "uploaded to the server and distributed to trusted contacts to help "
+          "establish an authenticated channel during the Nearby Share flow. "
+          "This crypto data can be immediately invalidated by the local device "
+          "at any time without needing to communicate with the server. For "
+          "example, it expires after three days and new data needs to be "
+          "uploaded. Crypto data is also invalidated if the user's list of "
+          "allowed contacts changes. The server returns the local device "
+          "user's full name and icon URL if available on the Google server."
+        trigger:
+          "Automatically called daily to retrieve any updates to the user's "
+          "full name or icon URL. This request is also sent whenever the user "
+          "changes their device name in settings, whenever the user changes "
+          "their list of allowed contacts, or whenever new crypto data is "
+          "generated by the local device and needs to be shared with trusted "
+          "contacts."
+        data:
+          "Sends an OAuth 2.0 token, the local device's name, contact, and/or "
+          "Nearby-Share-specific crypto data. Possibly receives the user's "
+          "full name and icon URL from the Google server."
+        destination: GOOGLE_OWNED_SERVICE
+      }
+      policy {
+        setting:
+          "Only sent when Nearby Share is enabled and the user is signed in "
+          "with their Google account."
+        chrome_policy {
+          SigninAllowed {
+            SigninAllowed: false
+          }
+        }
+      })"));
+  return *annotation;
+}
+
+// TODO(crbug.com/1103471): Update "chrome_policy" when a Nearby Share
+// enterprise policy is created.
+const net::PartialNetworkTrafficAnnotationTag& GetContactsAnnotation() {
+  static const base::NoDestructor<net::PartialNetworkTrafficAnnotationTag>
+      annotation(net::DefinePartialNetworkTrafficAnnotation(
+          "nearby_share_contacts", "oauth2_api_call_flow",
+          R"(
+      semantics {
+        sender: "Nearby Share"
+        description:
+          "Used as part of the Nearby Share feature that allows users to "
+          "share files or text with trusted contacts within a certain physical "
+          "proximity. The call retrieves the user's list of contacts from the "
+          "Google-owned People server via the Google-owned Nearby server."
+        trigger:
+          "Called multiple times a day to check for possible updates to the "
+          "users's contact list. It is also invoked during Nearby Share "
+          "onboarding and when the user is in the Nearby Share settings."
+        data:
+          "Sends an OAuth 2.0 token. Receives the user's contact list, which "
+          "includes phone numbers and email addresses."
+        destination: GOOGLE_OWNED_SERVICE
+      }
+      policy {
+        setting:
+          "Only sent when Nearby Share is enabled and the user is signed in "
+          "with their Google account."
+        chrome_policy {
+          SigninAllowed {
+            SigninAllowed: false
+          }
+        }
+          })"));
+  return *annotation;
+}
+
+// TODO(crbug.com/1103471): Update "chrome_policy" when a Nearby Share
+// enterprise policy is created.
+const net::PartialNetworkTrafficAnnotationTag&
+GetListPublicCertificatesAnnotation() {
+  static const base::NoDestructor<net::PartialNetworkTrafficAnnotationTag>
+      annotation(net::DefinePartialNetworkTrafficAnnotation(
+          "nearby_share_list_public_certificates", "oauth2_api_call_flow",
+          R"(
+      semantics {
+        sender: "Nearby Share"
+        description:
+          "Used as part of the Nearby Share feature that allows users to "
+          "share files or text with trusted contacts within a certain physical "
+          "proximity. The call retrieves Nearby-Share-specific crypto data "
+          "from the Google-owned Nearby server. The data was uploaded by other "
+          "devices and is needed to establish an authenticated connection with "
+          "those device during the Nearby Share flow."
+        trigger:
+          "Automatically called at least once a day to retrieve any updates to "
+          "the list of crypto data. It is also called when Nearby Share is in "
+          "use to ensure up-to-date data."
+        data:
+          "Sends an OAuth 2.0 token. Receives Nearby-Share-specific crypto "
+          "necessary for establishing an authenticated channel with other "
+          "devices."
+        destination: GOOGLE_OWNED_SERVICE
+      }
+      policy {
+        setting:
+          "Only sent when Nearby Share is enabled and the user is signed in "
+          "with their Google account."
+        chrome_policy {
+          SigninAllowed {
+            SigninAllowed: false
+          }
+        }
+          })"));
+  return *annotation;
+}
+
 }  // namespace
 
 NearbyShareClientImpl::NearbyShareClientImpl(
@@ -103,55 +229,51 @@
 void NearbyShareClientImpl::UpdateDevice(
     const nearbyshare::proto::UpdateDeviceRequest& request,
     UpdateDeviceCallback&& callback,
-    ErrorCallback&& error_callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
+    ErrorCallback&& error_callback) {
   // TODO(cclem): Use correct device identifier
   MakeApiCall(CreateV1RequestUrl(kUpdateDevicePath + request.device().name()),
               RequestType::kPatch, request.SerializeAsString(),
-              base::nullopt /* request_as_query_parameters */,
+              /*request_as_query_parameters=*/base::nullopt,
               std::move(callback), std::move(error_callback),
-              partial_traffic_annotation);
+              GetUpdateDeviceAnnotation());
 }
 
 void NearbyShareClientImpl::CheckContactsReachability(
     const nearbyshare::proto::CheckContactsReachabilityRequest& request,
     CheckContactsReachabilityCallback&& callback,
-    ErrorCallback&& error_callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
+    ErrorCallback&& error_callback) {
   MakeApiCall(CreateV1RequestUrl(kCheckContactsReachabilityPath),
               RequestType::kPost, request.SerializeAsString(),
-              base::nullopt /* request_as_query_parameters */,
+              /*request_as_query_parameters=*/base::nullopt,
               std::move(callback), std::move(error_callback),
-              partial_traffic_annotation);
+              GetContactsAnnotation());
 }
 
 void NearbyShareClientImpl::ListContactPeople(
     const nearbyshare::proto::ListContactPeopleRequest& request,
     ListContactPeopleCallback&& callback,
-    ErrorCallback&& error_callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
+    ErrorCallback&& error_callback) {
   // TODO(cclem): Use correct identifier in URL
   MakeApiCall(CreateV1RequestUrl(kListContactPeoplePathSeg1 + request.parent() +
                                  kListContactPeoplePathSeg2),
-              RequestType::kGet, base::nullopt /* serialized_request */,
+              RequestType::kGet, /*serialized_request=*/base::nullopt,
               ListContactPeopleRequestToQueryParameters(request),
               std::move(callback), std::move(error_callback),
-              partial_traffic_annotation);
+              GetContactsAnnotation());
 }
 
 void NearbyShareClientImpl::ListPublicCertificates(
     const nearbyshare::proto::ListPublicCertificatesRequest& request,
     ListPublicCertificatesCallback&& callback,
-    ErrorCallback&& error_callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
+    ErrorCallback&& error_callback) {
   // TODO(cclem): Use correct identifier in URL
   MakeApiCall(
       CreateV1RequestUrl(kListPublicCertificatesPathSeg1 + request.parent() +
                          kListPublicCertificatesPathSeg2),
-      RequestType::kGet, base::nullopt /* serialized_request */,
+      RequestType::kGet, /*serialized_request=*/base::nullopt,
       ListPublicCertificatesRequestToQueryParameters(request),
       std::move(callback), std::move(error_callback),
-      partial_traffic_annotation);
+      GetListPublicCertificatesAnnotation());
 }
 
 std::string NearbyShareClientImpl::GetAccessTokenUsed() {
diff --git a/chrome/browser/nearby_sharing/client/nearby_share_client_impl.h b/chrome/browser/nearby_sharing/client/nearby_share_client_impl.h
index a48ac816..7facd0e 100644
--- a/chrome/browser/nearby_sharing/client/nearby_share_client_impl.h
+++ b/chrome/browser/nearby_sharing/client/nearby_share_client_impl.h
@@ -49,27 +49,19 @@
   // NearbyShareClient:
   void UpdateDevice(const nearbyshare::proto::UpdateDeviceRequest& request,
                     UpdateDeviceCallback&& callback,
-                    ErrorCallback&& error_callback,
-                    const net::PartialNetworkTrafficAnnotationTag&
-                        partial_traffic_annotation) override;
+                    ErrorCallback&& error_callback) override;
   void CheckContactsReachability(
       const nearbyshare::proto::CheckContactsReachabilityRequest& request,
       CheckContactsReachabilityCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
-      override;
+      ErrorCallback&& error_callback) override;
   void ListContactPeople(
       const nearbyshare::proto::ListContactPeopleRequest& request,
       ListContactPeopleCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
-      override;
+      ErrorCallback&& error_callback) override;
   void ListPublicCertificates(
       const nearbyshare::proto::ListPublicCertificatesRequest& request,
       ListPublicCertificatesCallback&& callback,
-      ErrorCallback&& error_callback,
-      const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
-      override;
+      ErrorCallback&& error_callback) override;
   std::string GetAccessTokenUsed() override;
 
  private:
diff --git a/chrome/browser/nearby_sharing/client/nearby_share_client_impl_unittest.cc b/chrome/browser/nearby_sharing/client/nearby_share_client_impl_unittest.cc
index 9b9ff8dd..3420ba8 100644
--- a/chrome/browser/nearby_sharing/client/nearby_share_client_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/client/nearby_share_client_impl_unittest.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/nearby_sharing/proto/device_rpc.pb.h"
 #include "chrome/browser/nearby_sharing/proto/rpc_resources.pb.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -242,8 +241,7 @@
       base::BindOnce(
           &SaveResultConstRef<nearbyshare::proto::UpdateDeviceResponse>,
           &result_proto),
-      base::BindOnce(&NotCalled<NearbyShareRequestError>),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&NotCalled<NearbyShareRequestError>));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -302,8 +300,7 @@
       request,
       base::BindOnce(
           &NotCalledConstRef<nearbyshare::proto::UpdateDeviceResponse>),
-      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -329,8 +326,7 @@
       base::BindOnce(&SaveResultConstRef<
                          nearbyshare::proto::CheckContactsReachabilityResponse>,
                      &result_proto),
-      base::BindOnce(&NotCalled<NearbyShareRequestError>),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&NotCalled<NearbyShareRequestError>));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -374,8 +370,7 @@
       request_proto,
       base::BindOnce(&NotCalledConstRef<
                      nearbyshare::proto::CheckContactsReachabilityResponse>),
-      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -401,8 +396,7 @@
       base::BindOnce(
           &SaveResultConstRef<nearbyshare::proto::ListContactPeopleResponse>,
           &result_proto),
-      base::BindOnce(&NotCalled<NearbyShareRequestError>),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&NotCalled<NearbyShareRequestError>));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -460,8 +454,7 @@
       base::BindOnce(&SaveResultConstRef<
                          nearbyshare::proto::ListPublicCertificatesResponse>,
                      &result_proto),
-      base::BindOnce(&NotCalled<NearbyShareRequestError>),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&NotCalled<NearbyShareRequestError>));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -534,8 +527,7 @@
       nearbyshare::proto::UpdateDeviceRequest(),
       base::BindOnce(
           &NotCalledConstRef<nearbyshare::proto::UpdateDeviceResponse>),
-      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
           GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
@@ -552,8 +544,7 @@
       request_proto,
       base::BindOnce(
           &NotCalledConstRef<nearbyshare::proto::UpdateDeviceResponse>),
-      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&SaveResult<NearbyShareRequestError>, &error));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -579,8 +570,7 @@
       base::BindOnce(
           &SaveResultConstRef<nearbyshare::proto::UpdateDeviceResponse>,
           &result_proto),
-      base::BindOnce(&NotCalled<NearbyShareRequestError>),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&NotCalled<NearbyShareRequestError>));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
@@ -598,8 +588,7 @@
         nearbyshare::proto::CheckContactsReachabilityRequest(),
         base::BindOnce(&NotCalledConstRef<
                        nearbyshare::proto::CheckContactsReachabilityResponse>),
-        base::BindOnce(&SaveResult<NearbyShareRequestError>, &error),
-        PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS));
+        base::BindOnce(&SaveResult<NearbyShareRequestError>, &error)));
   }
 
   // Complete first request.
@@ -624,8 +613,7 @@
         base::BindOnce(
             &SaveResultConstRef<nearbyshare::proto::UpdateDeviceResponse>,
             &result_proto),
-        base::BindOnce(&NotCalled<NearbyShareRequestError>),
-        PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+        base::BindOnce(&NotCalled<NearbyShareRequestError>));
     identity_test_environment_
         .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
             kAccessToken, base::Time::Max());
@@ -649,8 +637,7 @@
         nearbyshare::proto::CheckContactsReachabilityRequest(),
         base::BindOnce(&NotCalledConstRef<
                        nearbyshare::proto::CheckContactsReachabilityResponse>),
-        base::BindOnce(&SaveResult<NearbyShareRequestError>, &error),
-        PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS));
+        base::BindOnce(&SaveResult<NearbyShareRequestError>, &error)));
   }
 }
 
@@ -666,8 +653,7 @@
       base::BindOnce(
           &SaveResultConstRef<nearbyshare::proto::UpdateDeviceResponse>,
           &result_proto),
-      base::BindOnce(&NotCalled<NearbyShareRequestError>),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+      base::BindOnce(&NotCalled<NearbyShareRequestError>));
   identity_test_environment_
       .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
           kAccessToken, base::Time::Max());
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.cc b/chrome/browser/notifications/notification_platform_bridge_android.cc
index aa85252..e0058fd 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_android.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/notifications/notification_common.h"
 #include "chrome/browser/notifications/notification_display_service_impl.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
+#include "chrome/browser/profiles/profile_android.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/content_settings/core/common/pref_names.h"
@@ -276,6 +277,8 @@
       ConvertUTF8ToJavaString(env, notification.id());
   ScopedJavaLocalRef<jstring> j_origin =
       ConvertUTF8ToJavaString(env, origin_url.spec());
+  ScopedJavaLocalRef<jobject> android_profile =
+      ProfileAndroid::FromProfile(profile)->GetJavaObject();
   ScopedJavaLocalRef<jstring> title =
       ConvertUTF16ToJavaString(env, notification.title());
   ScopedJavaLocalRef<jstring> body =
@@ -309,7 +312,7 @@
 
   Java_NotificationPlatformBridge_displayNotification(
       env, java_object_, j_notification_id, j_notification_type, j_origin,
-      j_scope_url, j_profile_id, profile->IsOffTheRecord(), title, body, image,
+      j_scope_url, j_profile_id, android_profile, title, body, image,
       notification_icon, badge, vibration_pattern,
       notification.timestamp().ToJavaTime(), notification.renotify(),
       notification.silent(), actions);
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
index b19c1ccf2..87650c4 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -47,6 +47,8 @@
 #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-shared.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
 #include "ui/base/page_transition_types.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
@@ -335,6 +337,7 @@
 
     if (should_ignore_detected_ad &&
         (ad_id == previous_data->root_frame_tree_node_id())) {
+      page_ad_density_tracker_.RemoveRect(id_and_data->first);
       ad_frames_data_storage_.erase(id_and_data->second);
       ad_frames_data_.erase(id_and_data);
 
@@ -555,6 +558,35 @@
     ancestor_data->set_media_status(FrameData::MediaStatus::kPlayed);
 }
 
+void AdsPageLoadMetricsObserver::OnFrameIntersectionUpdate(
+    content::RenderFrameHost* render_frame_host,
+    const page_load_metrics::mojom::FrameIntersectionUpdate&
+        intersection_update) {
+  if (!intersection_update.main_frame_intersection_rect)
+    return;
+
+  int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
+  if (render_frame_host == GetDelegate().GetWebContents()->GetMainFrame()) {
+    page_ad_density_tracker_.UpdateMainFrameRect(
+        *intersection_update.main_frame_intersection_rect);
+    return;
+  }
+
+  // If the frame whose size has changed is the root of the ad ancestry chain,
+  // then update it.
+  FrameData* ancestor_data = FindFrameData(frame_tree_node_id);
+  if (ancestor_data &&
+      frame_tree_node_id == ancestor_data->root_frame_tree_node_id()) {
+    page_ad_density_tracker_.RemoveRect(frame_tree_node_id);
+    // Only add frames if they are visible.
+    if (!ancestor_data->is_display_none()) {
+      page_ad_density_tracker_.AddRect(
+          frame_tree_node_id,
+          *intersection_update.main_frame_intersection_rect);
+    }
+  }
+}
+
 void AdsPageLoadMetricsObserver::OnFrameDeleted(
     content::RenderFrameHost* render_frame_host) {
   if (!render_frame_host)
@@ -580,6 +612,7 @@
     ancestor_data->RecordAdFrameLoadUkmEvent(GetDelegate().GetSourceId());
     DCHECK(id_and_data->second != ad_frames_data_storage_.end());
     ad_frames_data_storage_.erase(id_and_data->second);
+    page_ad_density_tracker_.RemoveRect(id_and_data->first);
   }
 
   // Delete this frame's entry from the map now that the store is deleted.
@@ -710,6 +743,24 @@
     return;
   PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Resources.Bytes.Ads2",
                        aggregate_frame_data_->ad_network_bytes());
+
+  if (page_ad_density_tracker_.MaxPageAdDensityByArea() != -1) {
+    UMA_HISTOGRAM_PERCENTAGE("PageLoad.Clients.Ads.AdDensity.MaxPercentByArea",
+                             page_ad_density_tracker_.MaxPageAdDensityByArea());
+  }
+
+  if (page_ad_density_tracker_.MaxPageAdDensityByHeight() != -1) {
+    UMA_HISTOGRAM_PERCENTAGE(
+        "PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight",
+        page_ad_density_tracker_.MaxPageAdDensityByHeight());
+  }
+
+  // Records true if both of the density calculations succeeded on the page.
+  UMA_HISTOGRAM_BOOLEAN(
+      "PageLoad.Clients.Ads.AdDensity.Recorded",
+      page_ad_density_tracker_.MaxPageAdDensityByArea() != -1 &&
+          page_ad_density_tracker_.MaxPageAdDensityByHeight() != -1);
+
   auto* ukm_recorder = ukm::UkmRecorder::Get();
   ukm::builders::AdPageLoad builder(source_id);
   builder.SetTotalBytes(aggregate_frame_data_->network_bytes() >> 10)
@@ -721,7 +772,10 @@
                            FrameData::ResourceMimeType::kVideo) >>
                        10)
       .SetMainframeAdBytes(ukm::GetExponentialBucketMinForBytes(
-          main_frame_data_->ad_network_bytes()));
+          main_frame_data_->ad_network_bytes()))
+      .SetMaxAdDensityByArea(page_ad_density_tracker_.MaxPageAdDensityByArea())
+      .SetMaxAdDensityByHeight(
+          page_ad_density_tracker_.MaxPageAdDensityByHeight());
 
   // Record cpu metrics for the page.
   builder.SetAdCpuTime(
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
index 66c9785..07483ca9 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
@@ -14,6 +14,7 @@
 #include "base/scoped_observer.h"
 #include "base/time/tick_clock.h"
 #include "chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h"
+#include "chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h"
 #include "components/page_load_metrics/browser/page_load_metrics_observer.h"
 #include "components/page_load_metrics/common/page_load_metrics.mojom-forward.h"
 #include "components/subresource_filter/content/browser/subresource_filter_observer.h"
@@ -120,6 +121,10 @@
   void MediaStartedPlaying(
       const content::WebContentsObserver::MediaPlayerInfo& video_type,
       content::RenderFrameHost* render_frame_host) override;
+  void OnFrameIntersectionUpdate(
+      content::RenderFrameHost* render_frame_host,
+      const page_load_metrics::mojom::FrameIntersectionUpdate&
+          intersection_update) override;
   void OnFrameDeleted(content::RenderFrameHost* render_frame_host) override;
 
   void SetHeavyAdThresholdNoiseProviderForTesting(
@@ -270,6 +275,9 @@
   std::unique_ptr<HeavyAdThresholdNoiseProvider>
       heavy_ad_threshold_noise_provider_;
 
+  // The maximum ad density measurements for the page during it's lifecycle.
+  PageAdDensityTracker page_ad_density_tracker_;
+
   DISALLOW_COPY_AND_ASSIGN(AdsPageLoadMetricsObserver);
 };
 
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
index 8231fe19..166fc78c 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
@@ -83,6 +83,15 @@
 const char kHeavyAdInterventionTypeHistogramId[] =
     "PageLoad.Clients.Ads.HeavyAds.InterventionType2";
 
+const char kMaxAdDensityByAreaHistogramId[] =
+    "PageLoad.Clients.Ads.AdDensity.MaxPercentByArea";
+
+const char kMaxAdDensityByHeightHistogramId[] =
+    "PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight";
+
+const char kMaxAdDensityRecordedHistogramId[] =
+    "PageLoad.Clients.Ads.AdDensity.Recorded";
+
 const char kHttpOkResponseHeader[] =
     "HTTP/1.1 200 OK\r\n"
     "Content-Type: text/html; charset=utf-8\r\n"
@@ -237,6 +246,244 @@
       static_cast<int>(FrameData::OriginStatus::kCross));
 }
 
+// Verifies that the page ad density records the maximum value during
+// a page's lifecycling by creating a large ad frame, destroying it, and
+// creating a smaller iframe. The ad density recorded is the density with
+// the first larger frame.
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
+                       PageAdDensityRecordsPageMax) {
+  base::HistogramTester histogram_tester;
+  ukm::TestAutoSetUkmRecorder ukm_recorder;
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Evaluate the height and width of the page as the browser_test can
+  // vary the dimensions.
+  int document_height =
+      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
+  int document_width =
+      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
+
+  // Expectation is before NavigateToUrl for this test as the expectation can be
+  // met after NavigateToUrl and before the Wait.
+  waiter->AddMainFrameIntersectionExpectation(
+      gfx::Rect(0, 0, document_width,
+                document_height));  // Initial main frame rect.
+  ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL(
+                     "a.com", "/ads_observer/blank_with_adiframe_writer.html"));
+  waiter->Wait();
+  web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Create a frame at 100,100 of size 200,200.
+  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
+
+  // Create the frame with b.com as origin to not get caught by
+  // restricted ad tagging.
+  EXPECT_TRUE(ExecJs(
+      web_contents,
+      content::JsReplace(
+          "let frame = createAdIframeAtRect(100, 100, 200, 200); "
+          "frame.src = $1; ",
+          embedded_test_server()->GetURL("b.com", "/ads_observer/pixel.png"))));
+  waiter->Wait();
+
+  // Load should stop before we remove the frame.
+  EXPECT_TRUE(WaitForLoadStop(web_contents));
+  EXPECT_TRUE(ExecJs(web_contents,
+                     "let frames = document.getElementsByTagName('iframe'); "
+                     "frames[0].remove(); "));
+  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(400, 400, 10, 10));
+
+  // Delete the frame and create a new frame at 400,400 of size 10x10. The
+  // ad density resulting from this frame is lower than the 200x200.
+  EXPECT_TRUE(ExecJs(
+      web_contents,
+      content::JsReplace("let frame = createAdIframeAtRect(400, 400, 10, 10); "
+                         "frame.src = $1; ",
+                         embedded_test_server()
+                             ->GetURL("b.com", "/ads_observer/pixel.png")
+                             .spec())));
+  waiter->Wait();
+
+  // Evaluate the height and width of the page as the browser_test can
+  // vary the dimensions.
+  document_height =
+      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
+  document_width =
+      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
+
+  int page_area = document_width * document_height;
+  int ad_area = 200 * 200;  // The area of the first larger ad iframe.
+  int expected_page_density_area = ad_area * 100 / page_area;
+  int expected_page_density_height = 200 * 100 / document_height;
+
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityByAreaHistogramId,
+                                      expected_page_density_area, 1);
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityByHeightHistogramId,
+                                      expected_page_density_height, 1);
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityRecordedHistogramId, true,
+                                      1);
+  auto entries =
+      ukm_recorder.GetEntriesByName(ukm::builders::AdPageLoad::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  ukm_recorder.ExpectEntryMetric(
+      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByAreaName,
+      expected_page_density_area);
+  ukm_recorder.ExpectEntryMetric(
+      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByHeightName,
+      expected_page_density_height);
+}
+
+// Creates multiple overlapping frames and verifies the page ad density.
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
+                       PageAdDensityMultipleFrames) {
+  base::HistogramTester histogram_tester;
+  ukm::TestAutoSetUkmRecorder ukm_recorder;
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  int document_height =
+      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
+  int document_width =
+      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
+
+  // Expectation is before NavigateToUrl for this test as the expectation can be
+  // met after NavigateToUrl and before the Wait.
+  waiter->AddMainFrameIntersectionExpectation(
+      gfx::Rect(0, 0, document_width,
+                document_height));  // Initial main frame rect.
+
+  ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL(
+                     "a.com", "/ads_observer/blank_with_adiframe_writer.html"));
+  waiter->Wait();
+  web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Create a frame of size 400,400 at 100,100.
+  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(400, 400, 100, 100));
+
+  // Create the frame with b.com as origin to not get caught by
+  // restricted ad tagging.
+  EXPECT_TRUE(ExecJs(
+      web_contents, content::JsReplace(
+                        "let frame = createAdIframeAtRect(400, 400, 100, 100); "
+                        "frame.src = $1",
+                        embedded_test_server()
+                            ->GetURL("b.com", "/ads_observer/pixel.png")
+                            .spec())));
+
+  waiter->Wait();
+
+  // Create a frame at of size 200,200 at 450,450.
+  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(450, 450, 200, 200));
+  EXPECT_TRUE(ExecJs(
+      web_contents, content::JsReplace(
+                        "let frame = createAdIframeAtRect(450, 450, 200, 200); "
+                        "frame.src = $1",
+                        embedded_test_server()
+                            ->GetURL("b.com", "/ads_observer/pixel.png")
+                            .spec())));
+  waiter->Wait();
+
+  // Evaluate the height and width of the page as the browser_test can
+  // vary the dimensions.
+  document_height =
+      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
+  document_width =
+      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
+
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+  int page_area = document_width * document_height;
+  // The area of the two iframes minus the area of the overlapping section.
+  int ad_area = 100 * 100 + 200 * 200 - 50 * 50;
+  int expected_page_density_area = ad_area * 100 / page_area;
+  int expected_page_density_height = 250 * 100 / document_height;
+
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityByAreaHistogramId,
+                                      expected_page_density_area, 1);
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityByHeightHistogramId,
+                                      expected_page_density_height, 1);
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityRecordedHistogramId, true,
+                                      1);
+  auto entries =
+      ukm_recorder.GetEntriesByName(ukm::builders::AdPageLoad::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  ukm_recorder.ExpectEntryMetric(
+      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByAreaName,
+      expected_page_density_area);
+  ukm_recorder.ExpectEntryMetric(
+      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByHeightName,
+      expected_page_density_height);
+}
+
+// Creates a frame with display:none styling and verifies that it has an
+// empty intersection with the main frame.
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
+                       PageAdDensityIgnoreDisplayNoneFrame) {
+  base::HistogramTester histogram_tester;
+  ukm::TestAutoSetUkmRecorder ukm_recorder;
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Evaluate the height and width of the page as the browser_test can
+  // vary the dimensions.
+  int document_height =
+      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
+  int document_width =
+      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
+
+  // Expectation is before NavigateToUrl for this test as the expectation can be
+  // met after NavigateToUrl and before the Wait.
+  waiter->AddMainFrameIntersectionExpectation(
+      gfx::Rect(0, 0, document_width,
+                document_height));  // Initial main frame rect.
+
+  ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL(
+                     "a.com", "/ads_observer/blank_with_adiframe_writer.html"));
+  waiter->Wait();
+  web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Create a frame at 100,100 of size 200,200. The expectation is an empty rect
+  // as the frame is display:none and as a result has no main frame
+  // intersection.
+  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(0, 0, 0, 0));
+
+  // Create the frame with b.com as origin to not get caught by
+  // restricted ad tagging.
+  EXPECT_TRUE(ExecJs(
+      web_contents, content::JsReplace(
+                        "let frame = createAdIframeAtRect(100, 100, 200, 200); "
+                        "frame.src = $1; "
+                        "frame.style.display = \"none\";",
+                        embedded_test_server()
+                            ->GetURL("b.com", "/ads_observer/pixel.png")
+                            .spec())));
+
+  waiter->Wait();
+
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityByAreaHistogramId, 0, 1);
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityByHeightHistogramId, 0, 1);
+  histogram_tester.ExpectUniqueSample(kMaxAdDensityRecordedHistogramId, true,
+                                      1);
+  auto entries =
+      ukm_recorder.GetEntriesByName(ukm::builders::AdPageLoad::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  ukm_recorder.ExpectEntryMetric(
+      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByAreaName, 0);
+  ukm_recorder.ExpectEntryMetric(
+      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByHeightName, 0);
+}
+
 // Each CreativeOriginStatus* browser test inputs a pointer to a frame object
 // representing the frame tree path of a website with with a (possibly null)
 // ad subframe, which itself may have linearly nested subframes.
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
index 8869f84..0de4bd9 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
@@ -242,6 +242,8 @@
 
   gfx::Size frame_size() const { return frame_size_; }
 
+  bool is_display_none() const { return is_display_none_; }
+
   MediaStatus media_status() const { return media_status_; }
 
   void set_media_status(MediaStatus media_status) {
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc
new file mode 100644
index 0000000..4daffc7
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc
@@ -0,0 +1,297 @@
+// 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/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/numerics/checked_math.h"
+#include "base/optional.h"
+
+namespace {
+
+// Calculates the combined length of a set of line segments. This counts
+// each overlapping area a single time and does not include areas where there
+// is no line segment.
+//
+// TODO(https://crbug.com/1068586): Optimize segment length calculation.
+// AddSegment and RemoveSegment are both logarithmic operations, making this
+// linearithmic with the number of segments. However the expected number
+// of segments at any given time in the density calculation is low.
+class SegmentLength {
+ public:
+  // An event to process corresponding to the left or right point of each
+  // line segment.
+  struct SegmentEvent {
+    SegmentEvent(int segment_id, int pos, bool is_segment_start)
+        : segment_id(segment_id),
+          pos(pos),
+          is_segment_start(is_segment_start) {}
+    SegmentEvent(const SegmentEvent& other) = default;
+
+    // Tiebreak with position with |is_segment_start| and |segment_id|.
+    bool operator<(const SegmentEvent& rhs) const {
+      if (pos == rhs.pos) {
+        if (segment_id == rhs.segment_id) {
+          return is_segment_start != rhs.is_segment_start;
+        } else {
+          return segment_id < rhs.segment_id;
+        }
+      } else {
+        return pos < rhs.pos;
+      }
+    }
+
+    int segment_id;
+    int pos;
+    bool is_segment_start;
+  };
+
+  // Iterators into the set of segment events for efficient removal of
+  // segment events by segment_id. Maintained by |segment_event_iterators_|.
+  struct SegmentEventSetIterators {
+    SegmentEventSetIterators(std::set<SegmentEvent>::iterator start,
+                             std::set<SegmentEvent>::iterator end)
+        : start_it(start), end_it(end) {}
+
+    SegmentEventSetIterators(const SegmentEventSetIterators& other) = default;
+
+    std::set<SegmentEvent>::const_iterator start_it;
+    std::set<SegmentEvent>::const_iterator end_it;
+  };
+
+  SegmentLength() = default;
+  ~SegmentLength() = default;
+
+  // Add a line segment to the set of active line segments, the segment
+  // corresponds to the bottom or top of a rect.
+  void AddSegment(int segment_id, int start, int end) {
+    // Safe as insert will never return an invalid iterator, it will
+    // point to the existing element if already in the set.
+    auto start_it =
+        active_segments_
+            .insert(SegmentEvent(segment_id, start, true /*is_segment_start*/))
+            .first;
+    auto end_it =
+        active_segments_
+            .insert(SegmentEvent(segment_id, end, false /*is_segment_start*/))
+            .first;
+
+    segment_event_iterators_.emplace(
+        segment_id, SegmentEventSetIterators(start_it, end_it));
+  }
+
+  // Remove a segment from the set of active line segmnets.
+  void RemoveSegment(int segment_id) {
+    auto it = segment_event_iterators_.find(segment_id);
+    DCHECK(it != segment_event_iterators_.end());
+
+    const SegmentEventSetIterators& set_its = it->second;
+    active_segments_.erase(set_its.start_it);
+    active_segments_.erase(set_its.end_it);
+    segment_event_iterators_.erase(segment_id);
+  }
+
+  // Calculate the combined length of segments in the active set of segments by
+  // iterating over the the sorted set of segment events.
+  base::Optional<int> Length() {
+    base::CheckedNumeric<int> length = 0;
+    int last_event_pos = -1;
+    int num_active = 0;
+    for (const auto& segment_event : active_segments_) {
+      if (last_event_pos == -1) {
+        DCHECK(segment_event.is_segment_start);
+        last_event_pos = segment_event.pos;
+      }
+
+      if (num_active > 0)
+        length += segment_event.pos - last_event_pos;
+
+      last_event_pos = segment_event.pos;
+      if (segment_event.is_segment_start) {
+        num_active += 1;
+      } else {
+        num_active -= 1;
+      }
+    }
+
+    base::Optional<int> total_length;
+    if (length.IsValid())
+      total_length = length.ValueOrDie();
+
+    return total_length;
+  }
+
+ private:
+  std::set<SegmentEvent> active_segments_;
+
+  // Map from the segment_id passed by user to the Segment struct.
+  std::unordered_map<int, SegmentEventSetIterators> segment_event_iterators_;
+
+  DISALLOW_COPY_AND_ASSIGN(SegmentLength);
+};
+
+}  // namespace
+
+PageAdDensityTracker::RectEvent::RectEvent(int id,
+                                           bool is_bottom,
+                                           const gfx::Rect& rect)
+    : rect_id(id), is_bottom(is_bottom), rect(rect) {}
+
+PageAdDensityTracker::RectEvent::RectEvent(const RectEvent& other) = default;
+
+PageAdDensityTracker::RectEventSetIterators::RectEventSetIterators(
+    std::set<RectEvent>::iterator top,
+    std::set<RectEvent>::iterator bottom)
+    : top_it(top), bottom_it(bottom) {}
+
+PageAdDensityTracker::RectEventSetIterators::RectEventSetIterators(
+    const RectEventSetIterators& other) = default;
+
+PageAdDensityTracker::PageAdDensityTracker() = default;
+
+PageAdDensityTracker::~PageAdDensityTracker() = default;
+
+int PageAdDensityTracker::MaxPageAdDensityByHeight() {
+  return max_page_ad_density_by_height_;
+}
+
+int PageAdDensityTracker::MaxPageAdDensityByArea() {
+  return max_page_ad_density_by_area_;
+}
+
+void PageAdDensityTracker::AddRect(int rect_id, const gfx::Rect& rect) {
+  // Check that we do not already have rect events for the rect.
+  DCHECK(rect_events_iterators_.find(rect_id) == rect_events_iterators_.end());
+
+  // We do not track empty rects.
+  if (rect.IsEmpty())
+    return;
+
+  // Limit the maximum number of rects tracked to 50 due to poor worst
+  // case performance.
+  const int kMaxRectsTracked = 50;
+  if (rect_events_iterators_.size() > kMaxRectsTracked)
+    return;
+
+  auto top_it =
+      rect_events_.insert(RectEvent(rect_id, true /*is_bottom*/, rect)).first;
+  auto bottom_it =
+      rect_events_.insert(RectEvent(rect_id, false /*is_bottom*/, rect)).first;
+  rect_events_iterators_.emplace(rect_id,
+                                 RectEventSetIterators(top_it, bottom_it));
+
+  // TODO(https://crbug.com/1068586): Improve performance by adding additional
+  // throttling to only calculate when max density can decrease (frame deleted
+  // or moved).
+  CalculateDensity();
+}
+
+void PageAdDensityTracker::RemoveRect(int rect_id) {
+  auto it = rect_events_iterators_.find(rect_id);
+
+  if (it == rect_events_iterators_.end())
+    return;
+
+  const RectEventSetIterators& set_its = it->second;
+  rect_events_.erase(set_its.top_it);
+  rect_events_.erase(set_its.bottom_it);
+  rect_events_iterators_.erase(rect_id);
+}
+
+void PageAdDensityTracker::UpdateMainFrameRect(const gfx::Rect& rect) {
+  if (!last_main_frame_size_ || rect != *last_main_frame_size_) {
+    last_main_frame_size_ = rect;
+    CalculateDensity();
+  }
+}
+
+// Ad density measurement uses a modified Bentley's Algorithm, the high level
+// approach is described on: http://jeffe.cs.illinois.edu/open/klee.html.
+void PageAdDensityTracker::CalculateDensity() {
+  // Cannot calculate density if there is no main frame rect.
+  if (!last_main_frame_size_)
+    return;
+
+  SegmentLength segment_length_tracker;
+
+  int last_y = -1;
+  base::CheckedNumeric<int> total_area = 0;
+  base::CheckedNumeric<int> total_height = 0;
+  for (const auto& rect_event : rect_events_) {
+    if (last_y == -1) {
+      DCHECK(rect_event.is_bottom);
+      segment_length_tracker.AddSegment(
+          rect_event.rect_id, rect_event.rect.x(),
+          rect_event.rect.x() + rect_event.rect.width());
+      last_y =
+          rect_event.is_bottom ? rect_event.rect.bottom() : rect_event.rect.y();
+    }
+
+    int current_y =
+        rect_event.is_bottom ? rect_event.rect.bottom() : rect_event.rect.y();
+    DCHECK_LE(current_y, last_y);
+
+    // If the segment length value is invalid, skip this ad density calculation.
+    base::Optional<int> segment_length = segment_length_tracker.Length();
+    if (!segment_length)
+      return;
+
+    // Check that the segment length multiplied by the height of the block
+    // does not overflow an int.
+    base::CheckedNumeric<int> current_area = *segment_length;
+    current_area *= (last_y - current_y);
+    if (!current_area.IsValid())
+      return;
+
+    total_area += *segment_length * (last_y - current_y);
+
+    if (*segment_length > 0)
+      total_height += (last_y - current_y);
+
+    // As we are iterating from the bottom of the page to the top, add segments
+    // when we see the start (bottom) of a new rect.
+    if (rect_event.is_bottom) {
+      segment_length_tracker.AddSegment(
+          rect_event.rect_id, rect_event.rect.x(),
+          rect_event.rect.x() + rect_event.rect.width());
+    } else {
+      segment_length_tracker.RemoveSegment(rect_event.rect_id);
+    }
+    last_y = current_y;
+  }
+
+  // If the measured height or area is invalid, skip recording this ad density
+  // calculation.
+  if (!total_height.IsValid() || !total_area.IsValid())
+    return;
+
+  base::CheckedNumeric<int> ad_density_by_height =
+      total_height * 100 / last_main_frame_size_->height();
+  if (ad_density_by_height.IsValid() &&
+      ad_density_by_height.ValueOrDie() > max_page_ad_density_by_height_)
+    max_page_ad_density_by_height_ = ad_density_by_height.ValueOrDie();
+
+  // Invalidate the check numeric if the checked area is invalid.
+  base::CheckedNumeric<int> ad_density_by_area =
+      total_area * 100 /
+      (last_main_frame_size_->size().GetCheckedArea().ValueOrDefault(0));
+  if (ad_density_by_area.IsValid() &&
+      ad_density_by_area.ValueOrDie() > max_page_ad_density_by_area_)
+    max_page_ad_density_by_area_ = ad_density_by_area.ValueOrDie();
+}
+
+bool PageAdDensityTracker::RectEvent::operator<(const RectEvent& rhs) const {
+  int lhs_y = is_bottom ? rect.bottom() : rect.y();
+  int rhs_y = rhs.is_bottom ? rhs.rect.bottom() : rhs.rect.y();
+
+  // Tiebreak with |rect_id| and |is_bottom|.
+  if (lhs_y == rhs_y) {
+    if (rect_id == rhs.rect_id) {
+      return is_bottom == rhs.is_bottom;
+    } else {
+      return rect_id < rhs.rect_id;
+    }
+  } else {
+    return lhs_y > rhs_y;
+  }
+}
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h
new file mode 100644
index 0000000..b2f013d
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h
@@ -0,0 +1,96 @@
+// 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_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_
+#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_
+
+#include <set>
+#include <unordered_map>
+
+#include "base/optional.h"
+#include "ui/gfx/geometry/rect.h"
+
+// Tracks the ad density of a page through the page's lifecycle.
+// It has the following usage:
+//    1. Set subframe and mainframe rects using subframe and mainframe rect
+//        operations (AddRect, RemoveRect, UpdateMainFrameRect).
+//    2. Once a page has a main frame rect, get current density using
+//        DensityByHeight or DensityByArea.
+class PageAdDensityTracker {
+ public:
+  PageAdDensityTracker();
+  ~PageAdDensityTracker();
+
+  PageAdDensityTracker(const PageAdDensityTracker&) = delete;
+  PageAdDensityTracker& operator=(const PageAdDensityTracker&) = delete;
+
+  // Operations to track sub frame rects in the page density calcluation.
+  void AddRect(int rect_id, const gfx::Rect& rect);
+
+  // Removes a rect from the tracker if it is currently being tracked.
+  // Otherwise RemoveRect is a no op.
+  void RemoveRect(int rect_id);
+
+  // Operations to track the main frame dimensions. The main frame rect has to
+  // be set to calculate density.
+  void UpdateMainFrameRect(const gfx::Rect& rect);
+
+  // Returns the density by height, as a value from 0-100. If the density
+  // calculation fails (i.e. no main frame size), this returns -1. Percentage
+  // density by height is calculated as the the combined height of ads divided
+  // by the page's height.
+  int MaxPageAdDensityByHeight();
+
+  // Returns the density by area, as a value from 0-100. If the density
+  // calculation fails (i.e. no main frame size), this returns -1.
+  int MaxPageAdDensityByArea();
+
+ private:
+  // An event to process corresponding to the top or bottom of each rect.
+  struct RectEvent {
+    RectEvent(int id, bool is_bottom, const gfx::Rect& rect);
+    RectEvent(const RectEvent& other);
+
+    // A unique identifier set when adding and removing rect events
+    // corresponding to a single rect.
+    int rect_id;
+    bool is_bottom;
+    gfx::Rect rect;
+
+    // RectEvents are sorted by descending y value of the segment associated
+    // with the event.
+    bool operator<(const RectEvent& rhs) const;
+  };
+
+  // Iterators into the set of rect events for efficient removal of
+  // rect events by rect_id. Maintained by |rect_events_iterators_|.
+  struct RectEventSetIterators {
+    RectEventSetIterators(std::set<RectEvent>::iterator top,
+                          std::set<RectEvent>::iterator bottom);
+    RectEventSetIterators(const RectEventSetIterators& other);
+
+    std::set<RectEvent>::const_iterator top_it;
+    std::set<RectEvent>::const_iterator bottom_it;
+  };
+
+  // Calculates the combined area and height of the set of rects, this populates
+  // total_height_ and total_area_.
+  void CalculateDensity();
+
+  // Maintain a sorted set of rect events for use in calculating ad area.
+  std::set<RectEvent> rect_events_;
+
+  // Map from rect_id to iterators of rect events in rect_events_. This allows
+  // efficient removal according to rect_id.
+  std::unordered_map<int, RectEventSetIterators> rect_events_iterators_;
+
+  // Percentage of page ad density as a value from 0-100. These only have
+  // a value of -1 when ad density has not yet been calculated successfully.
+  int max_page_ad_density_by_area_ = -1;
+  int max_page_ad_density_by_height_ = -1;
+
+  base::Optional<gfx::Rect> last_main_frame_size_;
+};
+
+#endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_"
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc
new file mode 100644
index 0000000..65d92c7
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_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 <limits>
+
+#include "chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
+
+TEST(PageAdDensityTrackerTest, MultipleRects_MaxPageDensityByAreaCalculated) {
+  PageAdDensityTracker tracker;
+
+  // Page ad density is -1 before there is a main frame or subframes.
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), -1);
+
+  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
+  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 10);
+
+  tracker.AddRect(2 /* rect_id */, gfx::Rect(5, 5, 100, 10));
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 15);
+
+  tracker.AddRect(3 /* rect_id */, gfx::Rect(50, 50, 50, 50));
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 40);
+
+  // Removing a rect should not change the maximum ad density.
+  tracker.RemoveRect(3 /* rect_id */);
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 40);
+}
+
+TEST(PageAdDensityTrackerTest, MultipleRects_MaxPageDensityByHeightCalculated) {
+  PageAdDensityTracker tracker;
+
+  // Page ad density is -1 before there is a main frame or subframes.
+  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), -1);
+
+  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
+  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
+  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 10);
+
+  tracker.AddRect(2 /* rect_id */, gfx::Rect(5, 5, 100, 10));
+  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 15);
+
+  tracker.AddRect(3 /* rect_id */, gfx::Rect(50, 50, 50, 50));
+  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 65);
+
+  // Removing a rect should not change the maximum ad density.
+  tracker.RemoveRect(3 /* rect_id */);
+  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 65);
+}
+
+// Remove a rect that was added twice, the second RemoveRect is
+// ignored as it is no longer being tracked.
+TEST(PageAdDensityTrackerTest, RemoveRectTwice_SecondRemoveIgnored) {
+  PageAdDensityTracker tracker;
+
+  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
+  tracker.RemoveRect(1 /* rect_id */);
+  tracker.RemoveRect(1 /* rect_id */);
+}
+
+// Ensures that two rects with the same dimensions hash to different
+// values in the density tracker's frame set.
+TEST(PageAdDensityTrackerTest, SeperateRects_SameDimensions) {
+  PageAdDensityTracker tracker;
+
+  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
+
+  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
+  tracker.AddRect(2 /* rect_id */, gfx::Rect(0, 0, 100, 10));
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 10);
+
+  tracker.RemoveRect(1 /* rect_id */);
+  tracker.RemoveRect(2 /* rect_id */);
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 10);
+}
+
+// Create 2 rects whose total area overflow an int.
+TEST(PageAdDensityTrackerTest, OverflowTotalAreaAndHeight) {
+  PageAdDensityTracker tracker;
+
+  tracker.AddRect(1 /* rect_id */, gfx::Rect(std::numeric_limits<int>::min(), 0,
+                                             std::numeric_limits<int>::max(),
+                                             std::numeric_limits<int>::max()));
+  tracker.AddRect(2 /* rect_id */, gfx::Rect(std::numeric_limits<int>::min(),
+                                             std::numeric_limits<int>::max(),
+                                             std::numeric_limits<int>::max(),
+                                             std::numeric_limits<int>::max()));
+
+  // Update main frame rect to force a calculation.
+  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
+
+  // Density should not be updated as the sum of area
+  // or height overflows.
+  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), -1);
+  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), -1);
+}
diff --git a/chrome/browser/paint_preview/android/BUILD.gn b/chrome/browser/paint_preview/android/BUILD.gn
index 5324f1b..b3fe7d1 100644
--- a/chrome/browser/paint_preview/android/BUILD.gn
+++ b/chrome/browser/paint_preview/android/BUILD.gn
@@ -18,7 +18,6 @@
 
   sources = [
     "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewDemoManager.java",
-    "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewExperiments.java",
     "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java",
     "java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java",
     "java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewDemoService.java",
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewExperiments.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewExperiments.java
deleted file mode 100644
index eec2b3e..0000000
--- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewExperiments.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.paint_preview;
-
-import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.components.paintpreview.browser.PaintPreviewUtils;
-import org.chromium.content_public.browser.WebContents;
-
-import java.util.Random;
-
-/**
- * Contains experiments related to the Paint Preview feature.
- */
-public class PaintPreviewExperiments {
-    private static Random sRandom = new Random();
-
-    /**
-     * Param name for field trial param that determines capture experiment trigger probability
-     * threshold.
-     **/
-    private static final String CAPTURE_EXPERIMENT_TRIGGER_PROBABILITY_THRESHOLD =
-            "capture_trigger_probability_threshold";
-
-    /**
-     * Runs the Paint Preview capture experiment if the experiment is enabled and a probability
-     * threshold is met. The probability threshold is determined by a field trial param.
-     * @param contents The WebContents of the page to capture.
-     */
-    public static void runCaptureExperiment(WebContents contents) {
-        // ChromeFeatureList and the Paint Preview component rely on native.
-        if (!LibraryLoader.getInstance().isInitialized()) {
-            return;
-        }
-
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.PAINT_PREVIEW_CAPTURE_EXPERIMENT)) {
-            return;
-        }
-
-        double captureTriggerProbabilityThreshold =
-                ChromeFeatureList.getFieldTrialParamByFeatureAsDouble(
-                        ChromeFeatureList.PAINT_PREVIEW_CAPTURE_EXPERIMENT,
-                        CAPTURE_EXPERIMENT_TRIGGER_PROBABILITY_THRESHOLD, 0);
-        if (sRandom.nextDouble() >= captureTriggerProbabilityThreshold) {
-            return;
-        }
-
-        PaintPreviewUtils.capturePaintPreview(contents);
-    }
-}
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java
index 45c6c10..f50f931 100644
--- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java
+++ b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java
@@ -77,13 +77,6 @@
         mPaintPreviewDemoManager.destroy();
     }
 
-    @Override
-    public void onPageLoadFinished(Tab tab, String url) {
-        if (qualifiesForCapture(tab)) {
-            PaintPreviewExperiments.runCaptureExperiment(tab.getWebContents());
-        }
-    }
-
     /**
      * Checks whether a given {@link Tab} qualifies for Paint Preview capture.
      */
diff --git a/chrome/browser/policy/arc_policy_browsertest.cc b/chrome/browser/policy/arc_policy_browsertest.cc
index 27cdb88..d8e13a4 100644
--- a/chrome/browser/policy/arc_policy_browsertest.cc
+++ b/chrome/browser/policy/arc_policy_browsertest.cc
@@ -50,8 +50,7 @@
   void SetArcEnabledByPolicy(bool enabled) {
     PolicyMap policies;
     policies.Set(key::kArcEnabled, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                 POLICY_SOURCE_CLOUD,
-                 base::WrapUnique(new base::Value(enabled)), nullptr);
+                 POLICY_SOURCE_CLOUD, base::Value(enabled), nullptr);
     UpdateProviderPolicy(policies);
     if (browser()) {
       const PrefService* const prefs = browser()->profile()->GetPrefs();
@@ -95,11 +94,11 @@
 
   // Set ARC backup and restore to user control via policy.
   PolicyMap policies;
-  policies.Set(key::kArcBackupRestoreServiceEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(
-                   static_cast<int>(ArcServicePolicyValue::kUnderUserControl)),
-               nullptr);
+  policies.Set(
+      key::kArcBackupRestoreServiceEnabled, POLICY_LEVEL_MANDATORY,
+      POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+      base::Value(static_cast<int>(ArcServicePolicyValue::kUnderUserControl)),
+      nullptr);
   UpdateProviderPolicy(policies);
 
   // User choice should be honored now.
@@ -113,8 +112,7 @@
   // Set ARC backup and restore to disabled via policy.
   policies.Set(key::kArcBackupRestoreServiceEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(
-                   static_cast<int>(ArcServicePolicyValue::kDisabled)),
+               base::Value(static_cast<int>(ArcServicePolicyValue::kDisabled)),
                nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_FALSE(pref->GetBoolean(arc::prefs::kArcBackupRestoreEnabled));
@@ -126,8 +124,7 @@
   // Set ARC backup and restore to enabled via policy.
   policies.Set(key::kArcBackupRestoreServiceEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(
-                   static_cast<int>(ArcServicePolicyValue::kEnabled)),
+               base::Value(static_cast<int>(ArcServicePolicyValue::kEnabled)),
                nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(pref->GetBoolean(arc::prefs::kArcBackupRestoreEnabled));
@@ -172,13 +169,12 @@
       if (test_policy_value.is_int()) {
         policies.Set(key::kArcGoogleLocationServicesEnabled,
                      POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                     POLICY_SOURCE_CLOUD, test_policy_value.CreateDeepCopy(),
-                     nullptr);
+                     POLICY_SOURCE_CLOUD, test_policy_value.Clone(), nullptr);
       }
       if (test_default_geo_policy_value.is_int()) {
         policies.Set(key::kDefaultGeolocationSetting, POLICY_LEVEL_MANDATORY,
                      POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                     test_default_geo_policy_value.CreateDeepCopy(), nullptr);
+                     test_default_geo_policy_value.Clone(), nullptr);
       }
       UpdateProviderPolicy(policies);
 
diff --git a/chrome/browser/policy/assistant_policy_browsertest.cc b/chrome/browser/policy/assistant_policy_browsertest.cc
index e178d44e..97192fc 100644
--- a/chrome/browser/policy/assistant_policy_browsertest.cc
+++ b/chrome/browser/policy/assistant_policy_browsertest.cc
@@ -28,8 +28,8 @@
   // Verifies that the Assistant context can be forced to always disabled.
   PolicyMap policies;
   policies.Set(key::kVoiceInteractionContextEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(false), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
+               nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(prefs->IsManagedPreference(
       chromeos::assistant::prefs::kAssistantContextEnabled));
@@ -41,8 +41,8 @@
 
   // Verifies that the Assistant context can be forced to always enabled.
   policies.Set(key::kVoiceInteractionContextEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(true), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(true),
+               nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(prefs->IsManagedPreference(
       chromeos::assistant::prefs::kAssistantContextEnabled));
@@ -67,8 +67,8 @@
   // Verifies that the Assistant hotword can be forced to always disabled.
   PolicyMap policies;
   policies.Set(key::kVoiceInteractionHotwordEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(false), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
+               nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(prefs->IsManagedPreference(
       chromeos::assistant::prefs::kAssistantHotwordEnabled));
@@ -80,8 +80,8 @@
 
   // Verifies that the Assistant hotword can be forced to always enabled.
   policies.Set(key::kVoiceInteractionHotwordEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(true), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(true),
+               nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(prefs->IsManagedPreference(
       chromeos::assistant::prefs::kAssistantHotwordEnabled));
@@ -108,7 +108,7 @@
   PolicyMap policies;
   policies.Set(key::kVoiceInteractionQuickAnswersEnabled,
                POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(false), nullptr);
+               base::Value(false), nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(prefs->IsManagedPreference(
       chromeos::assistant::prefs::kAssistantQuickAnswersEnabled));
@@ -122,7 +122,7 @@
   // Verifies that the Quick Answers setting can be forced to always enabled.
   policies.Set(key::kVoiceInteractionQuickAnswersEnabled,
                POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(true), nullptr);
+               base::Value(true), nullptr);
   UpdateProviderPolicy(policies);
   EXPECT_TRUE(prefs->IsManagedPreference(
       chromeos::assistant::prefs::kAssistantQuickAnswersEnabled));
diff --git a/chrome/browser/policy/cast_policy_browsertest.cc b/chrome/browser/policy/cast_policy_browsertest.cc
index 01b1b34..a6f2c35 100644
--- a/chrome/browser/policy/cast_policy_browsertest.cc
+++ b/chrome/browser/policy/cast_policy_browsertest.cc
@@ -23,8 +23,8 @@
     PolicyTest::SetUpInProcessBrowserTestFixture();
     PolicyMap policies;
     policies.Set(key::kEnableMediaRouter, POLICY_LEVEL_MANDATORY,
-                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(enable), nullptr);
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(enable),
+                 nullptr);
     provider_.UpdateChromePolicy(policies);
   }
 };
@@ -47,8 +47,8 @@
     PolicyTest::SetUpInProcessBrowserTestFixture();
     PolicyMap policies;
     policies.Set(key::kShowCastIconInToolbar, POLICY_LEVEL_MANDATORY,
-                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(enable), nullptr);
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(enable),
+                 nullptr);
     provider_.UpdateChromePolicy(policies);
   }
 };
@@ -77,7 +77,7 @@
     PolicyMap policies;
     policies.Set(key::kMediaRouterCastAllowAllIPs, POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(is_enabled()), nullptr);
+                 base::Value(is_enabled()), nullptr);
     provider_.UpdateChromePolicy(policies);
   }
 
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index f71013b..8a69bc5 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -160,22 +160,21 @@
   GetExpectedDefaultPolicy(expected);
 
   expected->Set(key::kShowHomeButton, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true),
-                nullptr);
+                POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
   expected->Set(key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY,
-                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                std::make_unique<base::Value>(4), nullptr);
+                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(4),
+                nullptr);
   base::ListValue list;
   list.AppendString("dev.chromium.org");
   list.AppendString("youtube.com");
   expected->Set(key::kURLBlacklist, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
+                POLICY_SOURCE_CLOUD, list.Clone(), nullptr);
   expected->Set(key::kMaxInvalidationFetchDelay, POLICY_LEVEL_MANDATORY,
-                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                std::make_unique<base::Value>(1000), nullptr);
+                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(1000),
+                nullptr);
   expected->Set(key::kHomepageLocation, POLICY_LEVEL_RECOMMENDED,
-                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                std::make_unique<base::Value>(homepage), nullptr);
+                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(homepage),
+                nullptr);
 }
 
 }  // namespace
diff --git a/chrome/browser/policy/content_settings_policy_browsertest.cc b/chrome/browser/policy/content_settings_policy_browsertest.cc
index 3427930..07d5f03c 100644
--- a/chrome/browser/policy/content_settings_policy_browsertest.cc
+++ b/chrome/browser/policy/content_settings_policy_browsertest.cc
@@ -75,8 +75,7 @@
   PolicyMap policies;
   policies.Set(key::kDefaultCookiesSetting, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY),
-               nullptr);
+               base::Value(CONTENT_SETTING_SESSION_ONLY), nullptr);
   UpdateProviderPolicy(policies);
 }
 
@@ -127,8 +126,8 @@
   // Disable Javascript via policy.
   PolicyMap policies;
   policies.Set(key::kJavascriptEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(false), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
+               nullptr);
   UpdateProviderPolicy(policies);
   // Reload the page.
   ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
@@ -146,7 +145,7 @@
   EXPECT_FALSE(IsJavascriptEnabled(contents));
   policies.Set(key::kDefaultJavaScriptSetting, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(CONTENT_SETTING_ALLOW), nullptr);
+               base::Value(CONTENT_SETTING_ALLOW), nullptr);
   UpdateProviderPolicy(policies);
   ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
   EXPECT_TRUE(IsJavascriptEnabled(contents));
@@ -189,8 +188,7 @@
   // Set the policy to block Web Bluetooth.
   PolicyMap policies;
   policies.Set(key::kDefaultWebBluetoothGuardSetting, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(2), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(2), nullptr);
   UpdateProviderPolicy(policies);
 
   std::string rejection;
@@ -340,8 +338,7 @@
     PolicyMap policies;
     policies.Set(key::kScrollToTextFragmentEnabled, POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(IsScrollToTextFragmentEnabled()),
-                 nullptr);
+                 base::Value(IsScrollToTextFragmentEnabled()), nullptr);
     UpdateProviderPolicy(policies);
     PolicyTest::CreatedBrowserMainParts(browser_main_parts);
   }
diff --git a/chrome/browser/policy/cors_policy_browsertest.cc b/chrome/browser/policy/cors_policy_browsertest.cc
index f2365cb..b2eca83 100644
--- a/chrome/browser/policy/cors_policy_browsertest.cc
+++ b/chrome/browser/policy/cors_policy_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/test/scoped_feature_list.h"
+#include "base/values.h"
 #include "chrome/browser/policy/policy_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -72,7 +73,7 @@
   PolicyMap policies;
   policies.Set(key::kCorsMitigationList, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::ListValue>(), nullptr);
+               base::Value(base::Value::Type::LIST), nullptr);
   UpdateProviderPolicy(policies);
 
   // Now the list is managed, and it enforces the webRequest API to use the
@@ -99,8 +100,8 @@
   // returning a consistent value that returned at the first access.
   PolicyMap policies;
   policies.Set(key::kCorsLegacyModeEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(true), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(true),
+               nullptr);
   UpdateProviderPolicy(policies);
 
   EXPECT_TRUE(prefs->GetBoolean(prefs::kCorsLegacyModeEnabled));
@@ -110,8 +111,8 @@
 
   // Flip the value, and check again.
   policies.Set(key::kCorsLegacyModeEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(false), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
+               nullptr);
   UpdateProviderPolicy(policies);
 
   EXPECT_FALSE(prefs->GetBoolean(prefs::kCorsLegacyModeEnabled));
diff --git a/chrome/browser/policy/default_geolocation_policy_handler_unittest.cc b/chrome/browser/policy/default_geolocation_policy_handler_unittest.cc
index 10717e6..7f15bd0 100644
--- a/chrome/browser/policy/default_geolocation_policy_handler_unittest.cc
+++ b/chrome/browser/policy/default_geolocation_policy_handler_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/policy/default_geolocation_policy_handler.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "components/arc/arc_prefs.h"
 #include "components/content_settings/core/common/content_settings.h"
@@ -33,7 +32,7 @@
   PolicyMap policy;
   policy.Set(key::kDefaultGeolocationSetting, POLICY_LEVEL_MANDATORY,
              POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-             base::WrapUnique(new base::Value(CONTENT_SETTING_ALLOW)), nullptr);
+             base::Value(CONTENT_SETTING_ALLOW), nullptr);
   UpdateProviderPolicy(policy);
   EXPECT_FALSE(
       store_->GetValue(arc::prefs::kArcLocationServiceEnabled, nullptr));
@@ -47,7 +46,7 @@
   PolicyMap policy;
   policy.Set(key::kDefaultGeolocationSetting, POLICY_LEVEL_MANDATORY,
              POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-             base::WrapUnique(new base::Value(CONTENT_SETTING_BLOCK)), nullptr);
+             base::Value(CONTENT_SETTING_BLOCK), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* value = nullptr;
   EXPECT_TRUE(store_->GetValue(arc::prefs::kArcLocationServiceEnabled, &value));
@@ -62,7 +61,7 @@
   PolicyMap policy;
   policy.Set(key::kDefaultGeolocationSetting, POLICY_LEVEL_MANDATORY,
              POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-             base::WrapUnique(new base::Value(CONTENT_SETTING_ASK)), nullptr);
+             base::Value(CONTENT_SETTING_ASK), nullptr);
   UpdateProviderPolicy(policy);
   EXPECT_FALSE(
       store_->GetValue(arc::prefs::kArcLocationServiceEnabled, nullptr));
diff --git a/chrome/browser/policy/policy_network_browsertest.cc b/chrome/browser/policy/policy_network_browsertest.cc
index f2dc0eed..cdd1b43 100644
--- a/chrome/browser/policy/policy_network_browsertest.cc
+++ b/chrome/browser/policy/policy_network_browsertest.cc
@@ -172,8 +172,7 @@
  protected:
   void GetQuicAllowedPolicy(PolicyMap* values) override {
     values->Set(key::kQuicAllowed, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
-                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
-                nullptr);
+                POLICY_SOURCE_CLOUD, base::Value(false), nullptr);
   }
 
  private:
@@ -236,8 +235,7 @@
  protected:
   void GetQuicAllowedPolicy(PolicyMap* values) override {
     values->Set(key::kQuicAllowed, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
-                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true),
-                nullptr);
+                POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
   }
 
  private:
@@ -385,8 +383,7 @@
                             bool value) {
     PolicyMap policy_map;
     policy_map.Set(key::kQuicAllowed, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                   POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(value),
-                   nullptr);
+                   POLICY_SOURCE_CLOUD, base::Value(value), nullptr);
     provider->UpdateChromePolicy(policy_map);
     base::RunLoop().RunUntilIdle();
 
diff --git a/chrome/browser/policy/restore_on_startup_policy_browsertest.cc b/chrome/browser/policy/restore_on_startup_policy_browsertest.cc
index c83fe0a..74289e4 100644
--- a/chrome/browser/policy/restore_on_startup_policy_browsertest.cc
+++ b/chrome/browser/policy/restore_on_startup_policy_browsertest.cc
@@ -85,25 +85,20 @@
       expected_urls_.push_back(GURL(url));
     }
     PolicyMap policies;
-    policies.Set(
-        key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-        POLICY_SOURCE_CLOUD,
-        base::WrapUnique(new base::Value(SessionStartupPref::kPrefValueURLs)),
-        nullptr);
+    policies.Set(key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY,
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+                 base::Value(SessionStartupPref::kPrefValueURLs), nullptr);
     policies.Set(key::kRestoreOnStartupURLs, POLICY_LEVEL_MANDATORY,
-                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, urls.CreateDeepCopy(),
-                 nullptr);
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, urls.Clone(), nullptr);
     provider_.UpdateChromePolicy(policies);
   }
 
   void NTP() {
     // Verifies that policy can set the startup page to the NTP.
     PolicyMap policies;
-    policies.Set(
-        key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-        POLICY_SOURCE_CLOUD,
-        base::WrapUnique(new base::Value(SessionStartupPref::kPrefValueNewTab)),
-        nullptr);
+    policies.Set(key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY,
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+                 base::Value(SessionStartupPref::kPrefValueNewTab), nullptr);
     provider_.UpdateChromePolicy(policies);
     expected_urls_.push_back(GURL(chrome::kChromeUINewTabURL));
   }
@@ -111,11 +106,9 @@
   void Last() {
     // Verifies that policy can set the startup pages to the last session.
     PolicyMap policies;
-    policies.Set(
-        key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-        POLICY_SOURCE_CLOUD,
-        base::WrapUnique(new base::Value(SessionStartupPref::kPrefValueLast)),
-        nullptr);
+    policies.Set(key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY,
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+                 base::Value(SessionStartupPref::kPrefValueLast), nullptr);
     provider_.UpdateChromePolicy(policies);
     // This should restore the tabs opened at PRE_RunTest below.
     for (const auto* url : kRestoredURLs)
@@ -125,14 +118,12 @@
   void Blocked() {
     // Verifies that URLs are blocked during session restore.
     PolicyMap policies;
-    policies.Set(
-        key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-        POLICY_SOURCE_CLOUD,
-        std::make_unique<base::Value>(SessionStartupPref::kPrefValueLast),
-        nullptr);
-    auto urls = std::make_unique<base::Value>(base::Value::Type::LIST);
+    policies.Set(key::kRestoreOnStartup, POLICY_LEVEL_MANDATORY,
+                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+                 base::Value(SessionStartupPref::kPrefValueLast), nullptr);
+    base::Value urls(base::Value::Type::LIST);
     for (const auto* url_string : kRestoredURLs)
-      urls->Append(url_string);
+      urls.Append(url_string);
     policies.Set(key::kURLBlacklist, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                  POLICY_SOURCE_CLOUD, std::move(urls), nullptr);
     provider_.UpdateChromePolicy(policies);
diff --git a/chrome/browser/policy/site_isolation_policy_browsertest.cc b/chrome/browser/policy/site_isolation_policy_browsertest.cc
index 3c1c733..d9b0f14 100644
--- a/chrome/browser/policy/site_isolation_policy_browsertest.cc
+++ b/chrome/browser/policy/site_isolation_policy_browsertest.cc
@@ -90,7 +90,7 @@
 #endif
     values.Set(kPolicyName, policy::POLICY_LEVEL_MANDATORY,
                policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(policy_value), nullptr);
+               base::Value(policy_value), nullptr);
     provider_.UpdateChromePolicy(values);
   }
 
@@ -118,11 +118,11 @@
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
 
     policy::PolicyMap values;
-    values.Set(policy::key::kIsolateOrigins, policy::POLICY_LEVEL_MANDATORY,
-               policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(
-                   "https://policy1.example.org/,http://policy2.example.com"),
-               nullptr);
+    values.Set(
+        policy::key::kIsolateOrigins, policy::POLICY_LEVEL_MANDATORY,
+        policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+        base::Value("https://policy1.example.org/,http://policy2.example.com"),
+        nullptr);
     provider_.UpdateChromePolicy(values);
   }
 
@@ -168,11 +168,11 @@
 
   // Simulate updating the policy at "browser runtime".
   policy::PolicyMap values;
-  values.Set(policy::key::kIsolateOrigins, policy::POLICY_LEVEL_MANDATORY,
-             policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-             std::make_unique<base::Value>(
-                 "https://policy3.example.org/,http://policy4.example.com"),
-             nullptr);
+  values.Set(
+      policy::key::kIsolateOrigins, policy::POLICY_LEVEL_MANDATORY,
+      policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+      base::Value("https://policy3.example.org/,http://policy4.example.com"),
+      nullptr);
   provider_.UpdateChromePolicy(values);
 
   // Verify that the policy update above has taken effect:
diff --git a/chrome/browser/policy/system_features_policy_browsertest.cc b/chrome/browser/policy/system_features_policy_browsertest.cc
index 5de6628..bdd3792 100644
--- a/chrome/browser/policy/system_features_policy_browsertest.cc
+++ b/chrome/browser/policy/system_features_policy_browsertest.cc
@@ -39,9 +39,8 @@
 
 IN_PROC_BROWSER_TEST_F(SystemFeaturesPolicyTest, DisableCameraBeforeInstall) {
   PolicyMap policies;
-  std::unique_ptr<base::Value> system_features =
-      std::make_unique<base::Value>(base::Value::Type::LIST);
-  system_features->Append(kCameraFeature);
+  base::Value system_features(base::Value::Type::LIST);
+  system_features.Append(kCameraFeature);
   policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                std::move(system_features), nullptr);
@@ -73,8 +72,7 @@
       });
 
   policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(), nullptr);
   UpdateProviderPolicy(policies);
 
   ASSERT_TRUE(
@@ -99,9 +97,8 @@
   base::RunLoop().RunUntilIdle();
 
   PolicyMap policies;
-  std::unique_ptr<base::Value> system_features =
-      std::make_unique<base::Value>(base::Value::Type::LIST);
-  system_features->Append(kCameraFeature);
+  base::Value system_features(base::Value::Type::LIST);
+  system_features.Append(kCameraFeature);
   policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                std::move(system_features), nullptr);
@@ -124,8 +121,7 @@
       });
 
   policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(), nullptr);
   UpdateProviderPolicy(policies);
 
   ASSERT_TRUE(
@@ -142,9 +138,8 @@
 
 IN_PROC_BROWSER_TEST_F(SystemFeaturesPolicyTest, RedirectChromeSettingsURL) {
   PolicyMap policies;
-  std::unique_ptr<base::Value> system_features =
-      std::make_unique<base::Value>(base::Value::Type::LIST);
-  system_features->Append(kBrowserSettingsFeature);
+  base::Value system_features(base::Value::Type::LIST);
+  system_features.Append(kBrowserSettingsFeature);
   policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                std::move(system_features), nullptr);
@@ -155,8 +150,7 @@
             GetWebUITitle(settings_url));
 
   policies.Set(key::kSystemFeaturesDisableList, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(), nullptr);
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(), nullptr);
   UpdateProviderPolicy(policies);
 
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_SETTINGS_SETTINGS),
diff --git a/chrome/browser/predictors/loading_predictor_browsertest.cc b/chrome/browser/predictors/loading_predictor_browsertest.cc
index 63bd581..c6bb68fd 100644
--- a/chrome/browser/predictors/loading_predictor_browsertest.cc
+++ b/chrome/browser/predictors/loading_predictor_browsertest.cc
@@ -31,6 +31,9 @@
 #include "chrome/browser/predictors/preconnect_manager.h"
 #include "chrome/browser/predictors/predictors_enums.h"
 #include "chrome/browser/predictors/predictors_features.h"
+#include "chrome/browser/prerender/prerender_handle.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/common/chrome_switches.h"
@@ -717,6 +720,71 @@
       preconnect_manager_observer()->HasOriginAttemptedToPreconnect(GURL()));
 }
 
+namespace {
+class TestPrerenderStopObserver : public prerender::PrerenderHandle::Observer {
+ public:
+  explicit TestPrerenderStopObserver(base::OnceClosure on_stop_closure)
+      : on_stop_closure_(std::move(on_stop_closure)) {}
+  ~TestPrerenderStopObserver() override = default;
+
+  void OnPrerenderStop(prerender::PrerenderHandle* contents) override {
+    if (on_stop_closure_) {
+      std::move(on_stop_closure_).Run();
+    }
+  }
+
+  void OnPrerenderStart(prerender::PrerenderHandle* handle) override {}
+  void OnPrerenderStopLoading(prerender::PrerenderHandle* handle) override {}
+  void OnPrerenderDomContentLoaded(
+      prerender::PrerenderHandle* handle) override {}
+  void OnPrerenderNetworkBytesChanged(
+      prerender::PrerenderHandle* handle) override {}
+
+ private:
+  base::OnceClosure on_stop_closure_;
+};
+}  // namespace
+
+// Tests that the LoadingPredictor doesn't preconnect during a prerender.
+IN_PROC_BROWSER_TEST_F(LoadingPredictorBrowserTest,
+                       PrepareForPageLoadDuringPrerender) {
+  GURL url("http://test.com");
+  base::RunLoop prerender_run_loop;
+  TestPrerenderStopObserver prerender_observer(
+      prerender_run_loop.QuitClosure());
+
+  prerender::PrerenderManager* prerender_manager =
+      prerender::PrerenderManagerFactory::GetForBrowserContext(
+          browser()->profile());
+
+  std::unique_ptr<prerender::PrerenderHandle> handle =
+      prerender_manager->AddPrerenderFromNavigationPredictor(
+          url,
+          browser()
+              ->tab_strip_model()
+              ->GetActiveWebContents()
+              ->GetController()
+              .GetDefaultSessionStorageNamespace(),
+          gfx::Size(640, 480));
+  ASSERT_TRUE(handle);
+  handle->SetObserver(&prerender_observer);
+  prerender_run_loop.Run();
+
+  url::Origin origin = url::Origin::Create(url);
+  net::NetworkIsolationKey network_isolation_key(origin, origin);
+  // Ensure that the prerender does not make a host lookup or attempt to
+  // preconnect.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(preconnect_manager_observer()->HasHostBeenLookedUp(
+      url.host(), network_isolation_key));
+  EXPECT_FALSE(preconnect_manager_observer()->HasHostBeenLookedUp(
+      "", network_isolation_key));
+  EXPECT_FALSE(preconnect_manager_observer()->HasOriginAttemptedToPreconnect(
+      url.GetOrigin()));
+  EXPECT_FALSE(
+      preconnect_manager_observer()->HasOriginAttemptedToPreconnect(GURL()));
+}
+
 // Tests that the LoadingPredictor preconnects to the main frame origin even if
 // it doesn't have any prediction for this origin.
 IN_PROC_BROWSER_TEST_F(LoadingPredictorBrowserTest,
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper.cc b/chrome/browser/predictors/loading_predictor_tab_helper.cc
index ea07832..57d1024 100644
--- a/chrome/browser/predictors/loading_predictor_tab_helper.cc
+++ b/chrome/browser/predictors/loading_predictor_tab_helper.cc
@@ -14,6 +14,8 @@
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/predictors/predictors_enums.h"
 #include "chrome/browser/predictors/predictors_features.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/optimization_guide/optimization_guide_decider.h"
 #include "components/optimization_guide/proto/hints.pb.h"
@@ -67,6 +69,16 @@
 }
 
 bool IsHandledNavigation(content::NavigationHandle* navigation_handle) {
+  content::WebContents* web_contents = navigation_handle->GetWebContents();
+
+  prerender::PrerenderManager* prerender_manager =
+      prerender::PrerenderManagerFactory::GetForBrowserContext(
+          web_contents->GetBrowserContext());
+  if (prerender_manager &&
+      prerender_manager->IsWebContentsPrerendering(web_contents, nullptr)) {
+    return false;
+  }
+
   return navigation_handle->IsInMainFrame() &&
          !navigation_handle->IsSameDocument() &&
          navigation_handle->GetURL().SchemeIsHTTPOrHTTPS();
diff --git a/chrome/browser/resources/chromeos/network_ui/network_ui.html b/chrome/browser/resources/chromeos/network_ui/network_ui.html
index 9c96e70..02a8d5b 100644
--- a/chrome/browser/resources/chromeos/network_ui/network_ui.html
+++ b/chrome/browser/resources/chromeos/network_ui/network_ui.html
@@ -2,6 +2,7 @@
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_select.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/onc_mojo.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network_health/network_diagnostics.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network_health/network_health_summary.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_tabs/cr_tabs.html">
@@ -37,7 +38,7 @@
         flex: 1;
         position: relative;
       }
-      
+
       network-select {
         flex: 1;
       }
@@ -86,6 +87,8 @@
       <div class="tabpanel" id="health">
         <h2>$i18n{networkHealthLabel}</h2>
         <network-health-summary></network-health-summary>
+        <h2>$i18n{networkDiagnosticsLabel}</h2>
+        <network-diagnostics></network-diagnostics>
       </div>
 
       <div class="tabpanel" id="logs">
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
index 60e9d9a..ef4547a0 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
+++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
@@ -67,7 +67,7 @@
     outline: none;
   }
 
-  .list-item[highlighted_] {
+  .list-item.highlighted {
     background-color: var(--google-blue-refresh-100);
   }
 
@@ -121,28 +121,38 @@
         no-cancel-on-esc-key>
       <div slot="dropdown-content">
         <template is="dom-repeat" items="[[itemList]]">
-          <button id="[[item.key]]" class="list-item" on-click="onSelect_"
-              tabindex="-1" value="[[item.key]]">
+          <button id="[[item.key]]" tabindex="-1" value="[[item.key]]"
+              on-click="onSelect_"
+              class$="list-item [[getHighlightedClass_(item.key,
+                  highlightedIndex_)]]">
             <printer-status-icon-cros background="white"
                 state$="[[computePrinterState_(item.printerStatusReason)]]">
             </printer-status-icon-cros>
             <span class="printer-display-name">[[item.displayName]]</span>
           </button>
         </template>
-        <button class="list-item" on-click="onSelect_" tabindex="-1"
-          value="[[pdfDestinationKey]]" hidden$="[[pdfPrinterDisabled]]">
+        <button on-click="onSelect_" tabindex="-1" value="[[pdfDestinationKey]]"
+          hidden$="[[pdfPrinterDisabled]]"
+          class$="list-item [[getHighlightedClass_(pdfDestinationKey,
+              highlightedIndex_)]]">
           $i18n{printToPDF}
         </button>
-        <button class="list-item" on-click="onSelect_" tabindex="-1"
-          value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]">
+        <button on-click="onSelect_" tabindex="-1"
+          value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]"
+          class$="list-item [[getHighlightedClass_(driveDestinationKey,
+              highlightedIndex_)]]">
           $i18n{printToGoogleDrive}
         </button>
-        <button class="list-item" on-click="onSelect_" tabindex="-1"
-          value="noDestinations" hidden$="[[!noDestinations]]">
+        <button on-click="onSelect_" tabindex="-1" value="noDestinations"
+          hidden$="[[!noDestinations]]"
+          class$="list-item [[getHighlightedClass_('noDestinations',
+              highlightedIndex_)]]">
           $i18n{noDestinationsMessage}
         </button>
-        <button class="list-item" on-click="onSelect_" tabindex="-1"
-          value="seeMore" aria-label$="[[i18n(seeMoreDestinationsLabel)]]">
+        <button on-click="onSelect_" tabindex="-1" value="seeMore"
+          aria-label$="[[i18n(seeMoreDestinationsLabel)]]"
+          class$="list-item [[getHighlightedClass_('seeMore',
+              highlightedIndex_)]]">
           $i18n{seeMore}
         </button>
       </div>
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js
index 6449a43..30317c4 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js
+++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js
@@ -51,6 +51,12 @@
     destinationIcon: String,
 
     isCurrentDestinationCrosLocal: Boolean,
+
+    /**
+     * Index of the highlighted item in the dropdown.
+     * @private
+     */
+    highlightedIndex_: Number,
   },
 
   listeners: {
@@ -90,12 +96,8 @@
       return;
     }
 
-    const selectedItem = this.getButtonListFromDropdown_().find(
+    this.highlightedIndex_ = this.getButtonListFromDropdown_().findIndex(
         item => item.value === this.value.key);
-    if (selectedItem) {
-      selectedItem.toggleAttribute('highlighted_', true);
-    }
-
     this.$$('iron-dropdown').open();
     this.opened_ = true;
   },
@@ -104,37 +106,24 @@
   closeDropdown_() {
     this.$$('iron-dropdown').close();
     this.opened_ = false;
-
-    const highlightedItem = this.findHighlightedItem_();
-    if (highlightedItem) {
-      highlightedItem.toggleAttribute('highlighted_', false);
-    }
+    this.highlightedIndex_ = -1;
   },
 
   /**
+   * Highlight the item the mouse is hovering over. If the user uses the
+   * keyboard, the highlight will shift. But once the user moves the mouse,
+   * the highlight should be updated based on the location of the mouse
+   * cursor.
    * @param {!Event} event
    * @private
    */
   onMouseMove_(event) {
-    const item = event.composedPath().find(
-        elm => elm.classList && elm.classList.contains('list-item'));
+    const item = /** @type {!Element} */ (event.composedPath().find(
+        elm => elm.classList && elm.classList.contains('list-item')));
     if (!item) {
       return;
     }
-
-    // Highlight the item the mouse is hovering over. If the user uses the
-    // keyboard, the highlight will shift. But once the user moves the mouse,
-    // the highlight should be updated based on the location of the mouse
-    // cursor.
-    const highlightedItem = this.findHighlightedItem_();
-    if (item === highlightedItem) {
-      return;
-    }
-
-    if (highlightedItem) {
-      highlightedItem.toggleAttribute('highlighted_', false);
-    }
-    item.toggleAttribute('highlighted_', true);
+    this.highlightedIndex_ = this.getButtonListFromDropdown_().indexOf(item);
   },
 
   /**
@@ -187,7 +176,8 @@
         break;
       case 'Enter': {
         if (dropdown.opened) {
-          this.dropdownValueSelected_(this.findHighlightedItem_());
+          this.dropdownValueSelected_(
+              this.getButtonListFromDropdown_()[this.highlightedIndex_]);
           break;
         }
         this.openDropdown_();
@@ -218,26 +208,23 @@
     // highlighted in the dropdown. If the dropdown is closed, use the arrow key
     // press to change the selected destination.
     if (dropdown.opened) {
-      const currentIndex =
-          items.findIndex(item => item.hasAttribute('highlighted_'));
-      const nextIndex =
-          this.getNextItemIndexInList_(eventCode, currentIndex, items.length);
+      const nextIndex = this.getNextItemIndexInList_(
+          eventCode, this.highlightedIndex_, items.length);
       if (nextIndex === -1) {
         return;
       }
-      items[currentIndex].toggleAttribute('highlighted_', false);
-      items[nextIndex].toggleAttribute('highlighted_', true);
-      items[nextIndex].focus();
-    } else {
-      const currentIndex =
-          items.findIndex(item => item.value === this.value.key);
-      const nextIndex =
-          this.getNextItemIndexInList_(eventCode, currentIndex, items.length);
-      if (nextIndex === -1) {
-        return;
-      }
-      this.fire('dropdown-value-selected', items[nextIndex]);
+      this.highlightedIndex_ = nextIndex;
+      items[this.highlightedIndex_].focus();
+      return;
     }
+
+    const currentIndex = items.findIndex(item => item.value === this.value.key);
+    const nextIndex =
+        this.getNextItemIndexInList_(eventCode, currentIndex, items.length);
+    if (nextIndex === -1) {
+      return;
+    }
+    this.fire('dropdown-value-selected', items[nextIndex]);
   },
 
   /**
@@ -266,17 +253,6 @@
   },
 
   /**
-   * Finds the currently highlighted dropdown item.
-   * @return {Element|undefined} Currently highlighted dropdown item, or
-   *   undefined if no item is highlighted.
-   * @private
-   */
-  findHighlightedItem_() {
-    const items = this.getButtonListFromDropdown_();
-    return items.find(item => item.hasAttribute('highlighted_'));
-  },
-
-  /**
    * Returns list of all the visible items in the dropdown.
    * @return {!Array<!Element>}
    * @private
@@ -312,4 +288,19 @@
     this.$$('#destination-dropdown')
         .setAttribute('tabindex', this.disabled ? '-1' : '0');
   },
+
+  /**
+   * Determines if an item in the dropdown should be highlighted based on the
+   * current value of |highlightedIndex_|.
+   * @param {string} itemValue
+   * @return {string}
+   * @private
+   */
+  getHighlightedClass_(itemValue) {
+    const itemToHighlight =
+        this.getButtonListFromDropdown_()[this.highlightedIndex_];
+    return itemToHighlight && itemValue === itemToHighlight.value ?
+        'highlighted' :
+        '';
+  },
 });
diff --git a/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chrome/browser/resources/settings/autofill_page/BUILD.gn
index 86fbde9..7a27294 100644
--- a/chrome/browser/resources/settings/autofill_page/BUILD.gn
+++ b/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -248,12 +248,15 @@
 
 js_library("password_remove_dialog") {
   deps = [
+    ":avatar_icon",
     ":multi_store_password_ui_entry",
+    "../people_page:sync_browser_proxy.m",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
     "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
     "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:i18n_behavior.m",
   ]
 }
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.html b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.html
index 0a5630c..71e3e41 100644
--- a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.html
@@ -1,4 +1,4 @@
-<style>
+<style include="cr-shared-style">
   cr-checkbox {
     display: flex;
     padding: 10px 8px;
@@ -7,18 +7,31 @@
   .checkbox-label {
     color: var(--google-grey-800);
   }
+
+  settings-avatar-icon {
+    height: 20px;
+    margin-inline-end: 16px;
+    width: 20px;
+  }
+
+  .cr-row {
+    padding: 0;
+  }
 </style>
 <cr-dialog id="dialog" close-text="$i18n{close}">
   <div slot="title">$i18n{passwordRemoveDialogTitle}</div>
   <div slot="body">
-    <!-- TODO(crbug.com/1102294): Display the website and avatar. -->
-    <div>
-      $i18n{passwordRemoveDialogBody}
-    </div>
+    <div inner-h-t-m-l="[[getDialogBodyMessage_()]]"></div>
     <cr-checkbox checked="{{removeFromAccountChecked_}}"
         id="removeFromAccountCheckbox">
-      <div class="checkbox-label">
-        $i18n{passwordRemoveDialogFromAccountCheckboxLabel}
+      <div class="cr-row first">
+        <settings-avatar-icon></settings-avatar-icon>
+        <div class="checkbox-label">
+          $i18n{passwordRemoveDialogFromAccountCheckboxLabel}
+        </div>
+        <div class="cr-secondary-text">
+          &nbsp([[accountEmail_]])
+        </div>
       </div>
     </cr-checkbox>
     <cr-checkbox checked="{{removeFromDeviceChecked_}}"
diff --git a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js
index a136b23..8dd3b91 100644
--- a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js
+++ b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js
@@ -13,10 +13,15 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import {assert} from 'chrome://resources/js/assert.m.js';
+import 'chrome://resources/cr_elements/shared_style_css.m.js';
+import './avatar_icon.js';
 
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {SyncBrowserProxyImpl} from '../people_page/sync_browser_proxy.m.js';
+
 import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
 import {PasswordManagerImpl} from './password_manager_proxy.js';
 
@@ -30,6 +35,8 @@
 
   _template: html`{__html_template__}`,
 
+  behaviors: [I18nBehavior],
+
   properties: {
     /**
      * The password whose copies are to be removed.
@@ -55,6 +62,13 @@
       value: true,
     },
 
+    /**
+     * @private
+     */
+    accountEmail_: {
+      type: String,
+      value: '',
+    },
   },
 
   /** @override */
@@ -64,6 +78,15 @@
         this.duplicatedPassword.isPresentInAccount() &&
         this.duplicatedPassword.isPresentOnDevice());
     this.$.dialog.showModal();
+
+    SyncBrowserProxyImpl.getInstance().getStoredAccounts().then(accounts => {
+      // TODO(victorvianna): These checks just make testing easier because then
+      // there's no need to wait for getStoredAccounts() to resolve. Remove them
+      // and adapt the tests instead.
+      if (!!accounts && accounts.length > 0) {
+        this.accountEmail_ = accounts[0].email;
+      }
+    });
   },
 
   /**
@@ -100,5 +123,15 @@
    */
   shouldDisableRemoveButton_() {
     return !this.removeFromAccountChecked_ && !this.removeFromDeviceChecked_;
-  }
+  },
+
+  /**
+   * @private
+   * @return {string}
+   */
+  getDialogBodyMessage_() {
+    return this.i18nAdvanced(
+        'passwordRemoveDialogBody',
+        {substitutions: [this.duplicatedPassword.urls.shown], tags: ['b']});
+  },
 });
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
index 44fe62a..fe132c7 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
@@ -592,6 +592,12 @@
   auto_imports = os_settings_auto_imports
 }
 
+polymer_modulizer("pin_autosubmit_dialog") {
+  js_file = "pin_autosubmit_dialog.js"
+  html_file = "pin_autosubmit_dialog.html"
+  html_type = "dom-module"
+}
+
 polymer_modulizer("setup_pin_dialog") {
   js_file = "setup_pin_dialog.js"
   html_file = "setup_pin_dialog.html"
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.html b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.html
index f4fb82db..f2469ac0 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.html
@@ -14,6 +14,7 @@
 <link rel="import" href="fingerprint_browser_proxy.html">
 <link rel="import" href="lock_state_behavior.html">
 <link rel="import" href="setup_pin_dialog.html">
+<link rel="import" href="pin_autosubmit_dialog.html">
 <link rel="import" href="../../i18n_setup.html">
 <link rel="import" href="../../prefs/prefs_behavior.html">
 <link rel="import" href="../../prefs/prefs.html">
@@ -67,6 +68,11 @@
         opacity: var(--settings-disabled-opacity);
         pointer-events: none;
       }
+
+      #autosubmitToggle {
+        padding-inline-start: 16px;
+        width: 100%;
+      }
     </style>
 
     <div>
@@ -114,6 +120,17 @@
                   </div>
                 </div>
               </template>
+              <template is="dom-if"
+                  if="[[quickUnlockPinAutosubmitFeatureEnabled_]]">
+                <div id="autosubmitToggle"
+                    hidden="[[!hasPin]]">
+                  <settings-toggle-button id="enablePinAutoSubmit"
+                      pref="{{prefs.pin_unlock_autosubmit_enabled}}" no-set-pref
+                      on-settings-boolean-control-change="onPinAutosubmitChange_"
+                      label="$i18n{lockScreenPinAutoSubmit}">
+                  </settings-toggle-button>
+                </div>
+              </template>
             </cr-radio-group>
           </div>
         </div>
@@ -170,6 +187,13 @@
             on-close="onSetupPinDialogClose_">
         </settings-setup-pin-dialog>
       </template>
+
+      <template is="dom-if" if="[[showPinAutosubmitDialog_]]" restamp>
+        <settings-pin-autosubmit-dialog id="pinAutosubmitDialog"
+            auth-token="[[authToken]]"
+            on-close="onPinAutosubmitDialogClose_">
+        </settings-pin-autosubmit-dialog>
+      </template>
     </div>
   </template>
   <script src="lock_screen.js"></script>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
index e2951163..fb3b0aff 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
@@ -129,8 +129,24 @@
       readOnly: true,
     },
 
+    /**
+     * True if quick unlock settings should be displayed on this machine.
+     * @private
+     */
+    quickUnlockPinAutosubmitFeatureEnabled_: {
+      type: Boolean,
+      value() {
+        return loadTimeData.getBoolean(
+            'quickUnlockPinAutosubmitFeatureEnabled');
+      },
+      readOnly: true,
+    },
+
     /** @private */
     showSetupPinDialog_: Boolean,
+
+    /** @private */
+    showPinAutosubmitDialog_: Boolean,
   },
 
   /** @private {?settings.FingerprintBrowserProxy} */
@@ -160,6 +176,7 @@
 
     if (this.requestPasswordIfApplicable_()) {
       this.showSetupPinDialog_ = false;
+      this.showPinAutosubmitDialog_ = false;
     }
   },
 
@@ -178,6 +195,31 @@
   },
 
   /**
+   * @param {!Event} event
+   * @private
+   */
+  onPinAutosubmitChange_(event) {
+    const target = /** @type {!SettingsToggleButtonElement} */ (event.target);
+    if (!this.authToken) {
+      console.error('PIN autosubmit setting changed with expired token.');
+      target.checked = !target.checked;
+      return;
+    }
+
+    // Read-only preference. Changes will be reflected directly on the toggle.
+    const autosubmitEnabled = target.checked;
+    target.resetToPrefValue();
+
+    if (autosubmitEnabled) {
+      this.showPinAutosubmitDialog_ = true;
+    } else {
+      // Call quick unlock to disable the auto-submit option.
+      this.quickUnlockPrivate.setPinAutosubmitEnabled(
+          this.authToken.token, '' /* PIN */, false /*enabled*/, function() {});
+    }
+  },
+
+  /**
    * Called when the unlock type has changed.
    * @param {!string} selected The current unlock type.
    * @private
@@ -220,6 +262,7 @@
   onSetModesChanged_() {
     if (this.requestPasswordIfApplicable_()) {
       this.showSetupPinDialog_ = false;
+      this.showPinAutosubmitDialog_ = false;
       return;
     }
 
@@ -245,6 +288,12 @@
     cr.ui.focusWithoutInk(assert(this.$$('#setupPinButton')));
   },
 
+  /** @private */
+  onPinAutosubmitDialogClose_() {
+    this.showPinAutosubmitDialog_ = false;
+    cr.ui.focusWithoutInk(assert(this.$$('#enablePinAutoSubmit')));
+  },
+
   /**
    * Returns true if the setup pin section should be shown.
    * @param {!string} selectedUnlockType The current unlock type. Used to let
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
index 550dbe8..cf26cb29 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
@@ -183,7 +183,8 @@
             associated-control="[[$$('#lock-screen-subpage-trigger')]]">
           <settings-lock-screen id="lock-screen" set-modes="[[setModes_]]"
               prefs="{{prefs}}" auth-token="[[authToken_]]"
-              on-password-requested="onPasswordRequested_">
+              on-password-requested="onPasswordRequested_"
+              on-invalidate-auth-token-requested="onInvalidateTokenRequested_">
           </settings-lock-screen>
         </settings-subpage>
       </template>
@@ -227,6 +228,7 @@
 
     <template is="dom-if" if="[[showPasswordPromptDialog_]]" restamp>
       <settings-lock-screen-password-prompt-dialog
+          id="passwordDialog"
           on-close="onPasswordPromptDialogClose_"
           on-auth-token-obtained="onAuthTokenObtained_">
       </settings-lock-screen-password-prompt-dialog>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
index e717d60..ee889fe 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
@@ -192,10 +192,18 @@
     this.showPasswordPromptDialog_ = true;
   },
 
+  // Invalidate the token to trigger a password re-prompt. Used for PIN auto
+  // submit when too many attempts were made when using PrefStore based PIN.
+  onInvalidateTokenRequested_() {
+    this.authToken_ = undefined;
+  },
+
   /** @private */
   onPasswordPromptDialogClose_() {
+    console.log('\n\n\n onPasswordPromptDialogClose_ \n\n\n');
     this.showPasswordPromptDialog_ = false;
     if (!this.setModes_) {
+      console.log('\n\n\n navigateToPreviousRoute \n\n\n');
       settings.Router.getInstance().navigateToPreviousRoute();
     }
   },
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html
new file mode 100644
index 0000000..c8191f9
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html
@@ -0,0 +1,85 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.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/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="../../i18n_setup.html">
+<link rel="import" href="../../settings_shared_css.html">
+
+<dom-module id="settings-pin-autosubmit-dialog">
+  <template>
+    <style include="settings-shared">
+      cr-dialog::part(dialog) {
+        width: fit-content;
+      }
+
+      #errorIcon {
+        --iron-icon-height: var(--cr-icon-size);
+        --iron-icon-width: var(--cr-icon-size);
+        --iron-icon-fill-color: var(--google-red-600);
+        display: inline-block;
+      }
+
+      #invalidPinError {
+        align-items: center;
+        color: var(--google-red-600);
+        display: flex;
+        flex-direction: row;
+        height: 32px;
+        min-height: 0;
+      }
+
+      /* Hide this using visibility: hidden instead of hidden so that the
+         dialog does not resize when there are no problems to display. */
+      #invalidPinError[invisible] {
+        visibility: hidden;
+      }
+
+      #pinKeyboardDiv {
+        justify-content: center;
+        padding: 0;
+      };
+
+      #pinKeyboard {
+        --cr-input-placeholder-letter-spacing: normal;
+      }
+
+      #pinAutosubmitDialogSubtitle {
+        padding-bottom: 16px;
+      }
+    </style>
+    <cr-dialog id="dialog" on-close="close" close-text="$i18n{close}">
+      <div slot="title">$i18n{configurePinConfirmPinTitle}</div>
+      <div slot="body">
+        <div id="pinAutosubmitDialogSubtitle">
+          $i18n{pinAutoSubmitPrompt}
+        </div>
+        <!-- PIN keyboard -->
+        <div id="pinKeyboardDiv" class="settings-box continuation">
+          <pin-keyboard id="pinKeyboard" on-pin-change="onPinChange_"
+              on-submit="onPinSubmit_" value="{{pinValue_}}"
+              disabled="[[requestInProcess_]]"
+              enable-letters>
+            <div id="invalidPinError" invisible$="[[!pinIncorrect_]]">
+              <iron-icon id="errorIcon" icon="cr:error-outline"></iron-icon>
+              <span>$i18n{invalidPin}</span>
+            </div>
+          </pin-keyboard>
+        </div>
+      </div>
+      <div slot="button-container">
+        <cr-button id="cancelButton" class="cancel-button" on-click="onCancelTap_">
+          $i18n{cancel}
+        </cr-button>
+        <cr-button id="confirmButton" class="action-button" on-click="onPinSubmit_"
+            disabled="[[confirmButtonDisabled_]]">
+          $i18n{confirm}
+        </cr-button>
+      </div>
+    </cr-dialog>
+  </template>
+  <script src="pin_autosubmit_dialog.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js
new file mode 100644
index 0000000..5bf61b6
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js
@@ -0,0 +1,167 @@
+// 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.
+
+/**
+ * @fileoverview
+ * 'pin-autosubmit-confirmation-dialog' is a confirmation dialog that pops up
+ * when the user chooses to enable PIN auto submit. The user is prompted to
+ * enter their current PIN and if it matches the feature is enabled.
+ *
+ */
+
+Polymer({
+  is: 'settings-pin-autosubmit-dialog',
+
+  behaviors: [I18nBehavior],
+
+  properties: {
+    /**
+     * The current PIN keyboard value.
+     * @private
+     */
+    pinValue_: {
+      type: String,
+    },
+
+    /**
+     * Whether the entered PIN is incorrect.
+     * @private
+     */
+    pinIncorrect_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * Whether there is a request in process already. Disables the
+     * buttons, but leaves the cancel button actionable.
+     * @private
+     */
+    requestInProcess_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * Whether the confirm button should be disabled.
+     * @private
+     */
+    confirmButtonDisabled_: {
+      type: Boolean,
+      value: true,
+    },
+
+    /**
+     * Authentication token provided by lock-screen-password-prompt-dialog.
+     * @type {!chrome.quickUnlockPrivate.TokenInfo|undefined}
+     */
+    authToken: {
+      type: Object,
+      notify: true,
+    },
+
+    /**
+     * Interface for chrome.quickUnlockPrivate calls. May be overridden by
+     * tests.
+     * @private
+     */
+    quickUnlockPrivate: {type: Object, value: chrome.quickUnlockPrivate},
+  },
+
+  observers: [
+    'updateButtonState_(pinIncorrect_, requestInProcess_, pinValue_)',
+  ],
+
+  /** @override */
+  attached() {
+    this.resetState();
+    this.$.dialog.showModal();
+    this.$.pinKeyboard.focusInput();
+  },
+
+  close() {
+    if (this.$.dialog.open) {
+      this.$.dialog.close();
+    }
+    this.resetState();
+  },
+
+  resetState() {
+    this.requestInProcess_ = false;
+    this.pinValue_ = '';
+    this.pinIncorrect_ = false;
+  },
+
+  /** @private */
+  onCancelTap_() {
+    this.close();
+  },
+
+  /**
+   * Reset the PIN field after error.
+   * @private
+   */
+  onPinChange_() {
+    if (this.pinIncorrect_) {
+      this.pinValue_ = '';
+      this.pinIncorrect_ = false;
+    }
+  },
+
+  /**
+   * Make a request to the quick unlock API to enable PIN auto-submit.
+   * @private
+   */
+  onPinSubmit_() {
+    // Make a request to enable pin autosubmit.
+    this.requestInProcess_ = true;
+    this.quickUnlockPrivate.setPinAutosubmitEnabled(
+        this.authToken.token, this.pinValue_ /* PIN */, true /*enabled*/,
+        this.onPinSubmitResponse_.bind(this));
+  },
+
+  /**
+   * Response from the quick unlock API.
+   *
+   * If the call is not successful because the PIN is incorrect,
+   * it will check if its still possible to authenticate with PIN.
+   * Submitting an invalid PIN will either show an error to the user,
+   * or close the dialog and trigger a password re-prompt.
+   * @param {Boolean} success
+   * @private
+   */
+  onPinSubmitResponse_(success) {
+    if (success) {
+      this.close();
+      return;
+    }
+    // Check if it is still possible to authenticate with pin.
+    this.quickUnlockPrivate.canAuthenticatePin(
+        this.onCanAuthenticateResponse_.bind(this));
+  },
+
+  /**
+   * Response from the quick unlock API on whether PIN authentication
+   * is currently possible.
+   * @param {Boolean} can_authenticate
+   */
+  onCanAuthenticateResponse_(can_authenticate) {
+    if (!can_authenticate) {
+      this.fire('invalidate-auth-token-requested');
+      this.close();
+      return;
+    }
+
+    this.pinValue_ = '';
+    this.requestInProcess_ = false;
+    this.pinIncorrect_ = true;
+    this.$.pinKeyboard.focusInput();
+  },
+
+  /** @private */
+  updateButtonState_() {
+    this.confirmButtonDisabled_ = this.requestInProcess_ ||
+        this.pinIncorrect_ || (this.pinValue_ && this.pinValue_.length === 0);
+  },
+});
diff --git a/chrome/browser/resources/settings/os_settings_resources.grd b/chrome/browser/resources/settings/os_settings_resources.grd
index 098af06..9cc11d9 100644
--- a/chrome/browser/resources/settings/os_settings_resources.grd
+++ b/chrome/browser/resources/settings/os_settings_resources.grd
@@ -1375,6 +1375,12 @@
                  file="chromeos/os_people_page/lock_state_behavior.html"
                  compress="false" type="chrome_html"
                  preprocess="true" />
+      <structure name="IDR_OS_SETTINGS_PEOPLE_PIN_AUTOSUBMIT_DIALOG_JS"
+                 file="chromeos/os_people_page/pin_autosubmit_dialog.js"
+                 compress="false" type="chrome_html" />
+      <structure name="IDR_OS_SETTINGS_PEOPLE_PIN_AUTOSUBMIT_DIALOG_HTML"
+                 file="chromeos/os_people_page/pin_autosubmit_dialog.html"
+                 compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_PEOPLE_SETUP_PIN_DIALOG_JS"
                  file="chromeos/os_people_page/setup_pin_dialog.js"
                  compress="false" type="chrome_html" />
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
index 68642ad0..54ea92c 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
@@ -307,7 +307,7 @@
                 mActivity.getResources().getString(R.string.sharing_highlights),
                 (currentActivity)
                         -> {
-                    RecordUserAction.record("SharingHubAndroid.SharedHighlights");
+                    RecordUserAction.record("SharingHubAndroid.LinkToTextSelected");
                     RecordHistogram.recordMediumTimesHistogram(
                             "Sharing.SharingHubAndroid.TimeToShare",
                             System.currentTimeMillis() - mShareStartTime);
diff --git a/chrome/browser/tabmodel/BUILD.gn b/chrome/browser/tabmodel/BUILD.gn
index 21fb576..ab77bd7 100644
--- a/chrome/browser/tabmodel/BUILD.gn
+++ b/chrome/browser/tabmodel/BUILD.gn
@@ -10,6 +10,7 @@
     "android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelSelectorObserver.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/NextTabPolicy.java",
+    "android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java",
@@ -26,6 +27,7 @@
     "//base:base_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
+    "//components/embedder_support/android:util_java",
     "//content/public/android:content_java",
   ]
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
rename to chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
diff --git a/chrome/browser/task_manager/providers/vm/vm_process_task_provider.cc b/chrome/browser/task_manager/providers/vm/vm_process_task_provider.cc
index e72a99df..3d15b04 100644
--- a/chrome/browser/task_manager/providers/vm/vm_process_task_provider.cc
+++ b/chrome/browser/task_manager/providers/vm/vm_process_task_provider.cc
@@ -103,38 +103,34 @@
   return true;
 }
 
-// We are looking for argument like this:
-// --params=/run/pvm-images/<cryptohome id>/UHZtRGVmYXVsdA==.pvm/...
+// We are looking for an argument like this:
+// /home/root/<cryptohome id>/pvm/UHZtRGVmYXVsdA==.pvm:/pvm:true
 bool PluginVmExtractVmNameAndOwnerId(const std::string& arg,
                                      std::string* vm_name_out,
                                      std::string* owner_id_out) {
   DCHECK(vm_name_out);
   DCHECK(owner_id_out);
 
-  constexpr char kParamPrefix[] = "--params=";
-  if (!base::StartsWith(arg, kParamPrefix, base::CompareCase::SENSITIVE)) {
+  constexpr char kArgStart[] = "/home/root/";
+  constexpr char kArgEnd[] = ":/pvm:true";
+
+  // Skip paths that don't start/end with the expected prefix/suffix.
+  if (!base::StartsWith(arg, kArgStart, base::CompareCase::SENSITIVE))
     return false;
-  }
-  base::StringPiece param(arg.begin() + strlen(kParamPrefix), arg.end());
-
-  // All VM disk images are mounted at this path.
-  constexpr char kVmDiskRoot[] = "/run/pvm-images/";
-
-  // Skip paths that don't start with the correct prefix.
-  if (!base::StartsWith(param, kVmDiskRoot, base::CompareCase::SENSITIVE)) {
+  if (!base::EndsWith(arg, kArgEnd, base::CompareCase::SENSITIVE))
     return false;
-  }
 
-  const base::FilePath vm_disk_path(param);
+  const base::FilePath vm_disk_path(
+      base::StringPiece(arg.begin(), arg.end() - strlen(kArgEnd)));
 
   std::vector<std::string> components;
   vm_disk_path.GetComponents(&components);
 
-  // Expect /, root, pvm-images, <owner_id>, vm_name.pvm, ...
-  if (components.size() < 5)
+  // Expect /, home, root, <owner_id>, pvm, vm_name.pvm
+  if (components.size() != 6)
     return false;
 
-  base::FilePath vm_subdir(components[4]);
+  base::FilePath vm_subdir(components[5]);
   if (vm_subdir.Extension() != ".pvm")
     return false;
 
@@ -142,9 +138,6 @@
   // file itself without the extension.
   base::Base64Decode(vm_subdir.RemoveExtension().value(), vm_name_out);
 
-  // The owner ID is the long hex string in there...which is 2 parents up.
-  // It's safe to call this even if there's not enough parents because the
-  // DirName of the root is still the root.
   *owner_id_out = components[3];
 
   return true;
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc
index 19b67dc0..82f3e6de 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc
@@ -2,13 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ash/public/cpp/accelerators.h"
+#include "ash/public/cpp/test/app_list_test_api.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/test/login_manager_mixin.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
@@ -67,6 +71,17 @@
   DISALLOW_COPY_AND_ASSIGN(OemAppPositionTest);
 };
 
+class AppPositionReorderingTest : public extensions::ExtensionBrowserTest {
+ public:
+  AppPositionReorderingTest() = default;
+  ~AppPositionReorderingTest() override = default;
+  AppPositionReorderingTest(const AppPositionReorderingTest& other) = delete;
+  AppPositionReorderingTest& operator=(const AppPositionReorderingTest& other) =
+      delete;
+
+ protected:
+  ash::AppListTestApi app_list_test_api_;
+};
 // Tests that an Oem app and its folder are created with valid positions after
 // sign-in.
 IN_PROC_BROWSER_TEST_F(OemAppPositionTest, ValidOemAppPosition) {
@@ -97,3 +112,73 @@
   ASSERT_TRUE(oem_folder);
   EXPECT_TRUE(oem_folder->position().IsValid());
 }
+
+IN_PROC_BROWSER_TEST_F(AppPositionReorderingTest,
+                       PRE_ReorderAppPositionInFolder) {
+  AppListClientImpl* client = AppListClientImpl::GetInstance();
+  ASSERT_TRUE(client);
+  client->UpdateProfile();
+
+  // Ensure async callbacks are run.
+  base::RunLoop().RunUntilIdle();
+
+  const std::string app1_id =
+      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
+  ASSERT_FALSE(app1_id.empty());
+  const std::string app2_id =
+      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
+  ASSERT_FALSE(app2_id.empty());
+  const std::string app4_id =
+      LoadExtension(test_data_dir_.AppendASCII("app4"))->id();
+  ASSERT_FALSE(app4_id.empty());
+
+  // Create the app list view and show the apps grid.
+  ash::AcceleratorController::Get()->PerformActionIfEnabled(
+      ash::TOGGLE_APP_LIST_FULLSCREEN, {});
+
+  // Create a folder with app1, app2 and app4 in order.
+  const std::string folder_id =
+      app_list_test_api_.CreateFolderWithApps({app1_id, app2_id, app4_id});
+
+  std::vector<std::string> original_id_list{app1_id, app2_id, app4_id};
+  ASSERT_EQ(app_list_test_api_.GetAppIdsInFolder(folder_id), original_id_list);
+
+  // Change an app position in the folder.
+  app_list_test_api_.MoveItemToPosition(app1_id, 2);
+
+  std::vector<std::string> reordered_id_list{app2_id, app4_id, app1_id};
+  EXPECT_EQ(app_list_test_api_.GetAppIdsInFolder(folder_id), reordered_id_list);
+}
+
+// Tests if the app position changed in a folder persist after the system
+// restart.
+IN_PROC_BROWSER_TEST_F(AppPositionReorderingTest, ReorderAppPositionInFolder) {
+  AppListClientImpl* client = AppListClientImpl::GetInstance();
+  ASSERT_TRUE(client);
+  client->UpdateProfile();
+
+  // Ensure async callbacks are run.
+  base::RunLoop().RunUntilIdle();
+
+  const std::string app1_id =
+      GetExtensionByPath(extension_registry()->enabled_extensions(),
+                         test_data_dir_.AppendASCII("app1"))
+          ->id();
+  const std::string app2_id =
+      GetExtensionByPath(extension_registry()->enabled_extensions(),
+                         test_data_dir_.AppendASCII("app2"))
+          ->id();
+  const std::string app4_id =
+      GetExtensionByPath(extension_registry()->enabled_extensions(),
+                         test_data_dir_.AppendASCII("app4"))
+          ->id();
+
+  std::string folder_id = app_list_test_api_.GetFolderId(app1_id);
+  // Check if the three apps are still in the same folder.
+  ASSERT_FALSE(folder_id.empty());
+  ASSERT_EQ(app_list_test_api_.GetFolderId(app2_id), folder_id);
+  ASSERT_EQ(app_list_test_api_.GetFolderId(app4_id), folder_id);
+
+  std::vector<std::string> reordered_id_list{app2_id, app4_id, app1_id};
+  EXPECT_EQ(app_list_test_api_.GetAppIdsInFolder(folder_id), reordered_id_list);
+}
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 06d29e1..43194051 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1340,8 +1340,7 @@
   // Set a policy that prevents the first-run dialog from being shown.
   policy_map_.Set(policy::key::kMetricsReportingEnabled,
                   policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                  policy::POLICY_SOURCE_CLOUD,
-                  std::make_unique<base::Value>(false), nullptr);
+                  policy::POLICY_SOURCE_CLOUD, base::Value(false), nullptr);
   provider_.UpdateChromePolicy(policy_map_);
 #endif  // defined(OS_LINUX) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
@@ -1400,18 +1399,16 @@
   // Set the following user policies:
   // * RestoreOnStartup = RestoreOnStartupIsURLs
   // * RestoreOnStartupURLs = [ "/title1.html" ]
-  policy_map_.Set(
-      policy::key::kRestoreOnStartup, policy::POLICY_LEVEL_MANDATORY,
-      policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-      base::WrapUnique(new base::Value(SessionStartupPref::kPrefValueURLs)),
-      nullptr);
+  policy_map_.Set(policy::key::kRestoreOnStartup,
+                  policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+                  policy::POLICY_SOURCE_CLOUD,
+                  base::Value(SessionStartupPref::kPrefValueURLs), nullptr);
   base::ListValue startup_urls;
   startup_urls.AppendString(
       embedded_test_server()->GetURL("/title1.html").spec());
   policy_map_.Set(policy::key::kRestoreOnStartupURLs,
                   policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                  policy::POLICY_SOURCE_CLOUD, startup_urls.CreateDeepCopy(),
-                  nullptr);
+                  policy::POLICY_SOURCE_CLOUD, startup_urls.Clone(), nullptr);
   provider_.UpdateChromePolicy(policy_map_);
   base::RunLoop().RunUntilIdle();
 
@@ -1530,8 +1527,7 @@
   // * RestoreOnStartupURLs = [ "/title1.html" ]
   policy_map_.Set(policy::key::kRestoreOnStartup,
                   policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
-                  policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(4),
-                  nullptr);
+                  policy::POLICY_SOURCE_CLOUD, base::Value(4), nullptr);
   auto url_list = std::make_unique<base::Value>(base::Value::Type::LIST);
   url_list->Append(
       base::Value(embedded_test_server()->GetURL("/title1.html").spec()));
@@ -1622,9 +1618,9 @@
       policy::PolicyMap values;
       values.Set(policy::key::kRestoreOnStartup, variant.value(),
                  policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(4), nullptr);
-      auto url_list = std::make_unique<base::Value>(base::Value::Type::LIST);
-      url_list->Append(base::Value("http://managed.site.com/"));
+                 base::Value(4), nullptr);
+      base::Value url_list(base::Value::Type::LIST);
+      url_list.Append("http://managed.site.com/");
       values.Set(policy::key::kRestoreOnStartupURLs, variant.value(),
                  policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
                  std::move(url_list), nullptr);
@@ -1750,8 +1746,8 @@
       policy::PolicyMap policies;
       policies.Set(policy::key::kCommandLineFlagSecurityWarningsEnabled,
                    policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
-                   policy::POLICY_SOURCE_PLATFORM,
-                   std::make_unique<base::Value>(is_enabled), nullptr);
+                   policy::POLICY_SOURCE_PLATFORM, base::Value(is_enabled),
+                   nullptr);
       policy_provider_.UpdateChromePolicy(policies);
     }
   }
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 77f2fb8..2a75d79 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
@@ -24,6 +24,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/native_theme/native_theme.h"
+#include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_border.h"
 #include "ui/views/focus/focus_manager.h"
@@ -142,6 +143,37 @@
   }
 }
 
+void AutofillPopupBaseView::VisibilityChanged(View* starting_from,
+                                              bool is_visible) {
+  if (!is_visible) {
+    if (is_ax_menu_start_event_fired_) {
+      // Fire menu end event.
+      // The menu start event is delayed until the user
+      // navigates into the menu, otherwise some screen readers will ignore
+      // any focus events outside of the menu, including a focus event on
+      // the form control itself.
+      NotifyAccessibilityEvent(ax::mojom::Event::kMenuEnd, true);
+      GetViewAccessibility().EndPopupFocusOverride();
+    }
+    is_ax_menu_start_event_fired_ = false;
+  }
+}
+
+void AutofillPopupBaseView::NotifyAXSelection(View* selected_view) {
+  DCHECK(selected_view);
+  if (!is_ax_menu_start_event_fired_) {
+    // Fire the menu start event once, right before the first item is selected.
+    // By firing these and the matching kMenuEnd events, we are telling screen
+    // readers that the focus is only changing temporarily, and the screen
+    // reader will restore the focus back to the appropriate textfield when the
+    // menu closes.
+    NotifyAccessibilityEvent(ax::mojom::Event::kMenuStart, true);
+    is_ax_menu_start_event_fired_ = true;
+  }
+  selected_view->GetViewAccessibility().SetPopupFocusOverride();
+  selected_view->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
+}
+
 void AutofillPopupBaseView::OnWidgetBoundsChanged(views::Widget* widget,
                                                   const gfx::Rect& new_bounds) {
   DCHECK(widget == parent_widget_ || widget == GetWidget());
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.h b/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
index b16bef4..9d8116f 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
+++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
@@ -36,6 +36,12 @@
 
   static int GetCornerRadius();
 
+  // views::View:
+  void VisibilityChanged(View* starting_from, bool is_visible) override;
+
+  // Notify accessibility that an item has been selected.
+  void NotifyAXSelection(View*);
+
   // Get colors used throughout various popup UIs, based on the current native
   // theme.
   SkColor GetBackgroundColor();
@@ -105,6 +111,9 @@
   // The time when the popup was shown.
   base::Time show_time_;
 
+  // Ensures that the menu start event is not fired redundantly.
+  bool is_ax_menu_start_event_fired_ = false;
+
   base::WeakPtrFactory<AutofillPopupBaseView> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupBaseView);
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index a0ec1ac..cb5fbeae 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -948,14 +948,8 @@
     return;
 
   is_selected_ = is_selected;
-  if (is_selected) {
-    // Before firing the selection event, ensure that focus appears to be
-    // within the popup. This is helpful for ATs on some platforms,
-    // specifically on Windows, where selection events in a list are mapped
-    // to focus events. Without this call, the focus appears to be in content.
-    GetViewAccessibility().SetPopupFocusOverride();
-    NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
-  }
+  if (is_selected)
+    popup_view_->NotifyAXSelection(this);
   RefreshStyle();
 }
 
@@ -1020,21 +1014,6 @@
       l10n_util::GetStringUTF16(IDS_AUTOFILL_POPUP_ACCESSIBLE_NODE_DATA));
 }
 
-void AutofillPopupViewNativeViews::VisibilityChanged(View* starting_from,
-                                                     bool is_visible) {
-  // Fire menu end event. The menu start event is delayed until the user
-  // navigates into the menu, otherwise some screen readers will ignore
-  // any focus events outside of the menu, including a focus event on
-  // the form control itself.
-  if (!is_visible) {
-    if (is_ax_menu_start_event_fired_) {
-      NotifyAccessibilityEvent(ax::mojom::Event::kMenuEnd, true);
-      GetViewAccessibility().EndPopupFocusOverride();
-    }
-    is_ax_menu_start_event_fired_ = false;
-  }
-}
-
 void AutofillPopupViewNativeViews::OnThemeChanged() {
   AutofillPopupBaseView::OnThemeChanged();
   SetBackground(views::CreateSolidBackground(GetBackgroundColor()));
@@ -1064,15 +1043,6 @@
 void AutofillPopupViewNativeViews::OnSelectedRowChanged(
     base::Optional<int> previous_row_selection,
     base::Optional<int> current_row_selection) {
-  if (!is_ax_menu_start_event_fired_) {
-    // By firing these and the matching kMenuEnd events, we are telling screen
-    // readers that the focus is only changing temporarily, and the screen
-    // reader will restore the focus back to the appropriate textfield when the
-    // menu closes.
-    NotifyAccessibilityEvent(ax::mojom::Event::kMenuStart, true);
-    is_ax_menu_start_event_fired_ = true;
-  }
-
   if (previous_row_selection) {
     rows_[*previous_row_selection]->SetSelected(false);
   }
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
index 013cb2adf..2a77c71 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
@@ -83,7 +83,6 @@
   // views::View:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnThemeChanged() override;
-  void VisibilityChanged(View* starting_from, bool is_visible) override;
 
   // AutofillPopupView:
   void Show() override;
@@ -120,8 +119,6 @@
   views::View* body_container_ = nullptr;
   views::View* footer_container_ = nullptr;
 
-  bool is_ax_menu_start_event_fired_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewNativeViews);
 };
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
index b699b1c..cc3a785 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -193,9 +193,16 @@
 bool BookmarkMenuDelegate::ShouldExecuteCommandWithoutClosingMenu(
     int id,
     const ui::Event& event) {
-  return (event.flags() & ui::EF_LEFT_MOUSE_BUTTON) &&
-         ui::DispositionFromEventFlags(event.flags()) ==
-             WindowOpenDisposition::NEW_BACKGROUND_TAB;
+  if ((event.flags() & ui::EF_LEFT_MOUSE_BUTTON) &&
+      ui::DispositionFromEventFlags(event.flags()) ==
+          WindowOpenDisposition::NEW_BACKGROUND_TAB) {
+    DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
+    const BookmarkNode* node = menu_id_to_node_map_[id];
+    // Close the menu before opening a folder since this may pop up a dialog
+    // over the menu. See https://crbug.com/1105587 for details.
+    return node->type() != BookmarkNode::FOLDER;
+  }
+  return false;
 }
 
 bool BookmarkMenuDelegate::GetDropFormats(
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 8ea2f5f..9bf7c242e 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -14,11 +14,13 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
+#include "base/containers/flat_map.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
 #include "base/numerics/math_constants.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/sys_string_conversions.h"
@@ -72,7 +74,6 @@
 #include "ui/base/text/bytes_formatting.h"
 #include "ui/base/theme_provider.h"
 #include "ui/events/event.h"
-#include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
@@ -133,9 +134,6 @@
 // Amount of time between accessible alert events.
 constexpr auto kAccessibleAlertInterval = base::TimeDelta::FromSeconds(30);
 
-// The size of the file icon.
-constexpr int kFileIconSize = 24;
-
 // The offset from the file icon to the danger icon.
 constexpr int kDangerIconOffset = 8;
 
@@ -229,6 +227,15 @@
       model_(std::move(download)),
       creation_time_(base::Time::Now()),
       time_download_warning_shown_(base::Time()),
+      indeterminate_progress_timer_(
+          FROM_HERE,
+          base::TimeDelta::FromMilliseconds(30),
+          base::BindRepeating(
+              [](DownloadItemView* view) {
+                if (view->model_->PercentComplete() < 0)
+                  view->SchedulePaint();
+              },
+              base::Unretained(this))),
       accessible_alert_(accessible_alert),
       announce_accessible_alert_soon_(false) {
   views::InstallRectHighlightPathGenerator(this);
@@ -299,12 +306,14 @@
   dropdown_button->SetFocusForPlatform();
   dropdown_button_ = AddChildView(std::move(dropdown_button));
 
+  complete_animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(2500));
+  complete_animation_.SetTweenType(gfx::Tween::LINEAR);
+
   // Further configure default state, e.g. child visibility.
   OnDownloadUpdated();
 }
 
 DownloadItemView::~DownloadItemView() {
-  StopDownloadProgress();
   model_->RemoveObserver(this);
 }
 
@@ -440,6 +449,8 @@
 
 void DownloadItemView::ButtonPressed(views::Button* sender,
                                      const ui::Event& event) {
+  // TODO(pkasting): Refactor to simplify.
+
   if (sender == open_now_button_) {
     OpenDownloadDuringAsyncScanning();
     return;
@@ -496,9 +507,19 @@
     }
     if (has_warning_label(mode_))
       return;
-    if (complete_animation_.get() && complete_animation_->is_animating())
-      complete_animation_->End();
-    OpenDownload();
+    complete_animation_.End();
+
+    // We're interested in how long it takes users to open downloads.  If they
+    // open downloads super quickly, we should be concerned about clickjacking.
+    UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
+                             base::Time::Now() - creation_time_);
+
+    // If this is still around for the next status update, it will be read.
+    announce_accessible_alert_soon_ = true;
+
+    // Calling download()->OpenDownload may delete this, so this must be
+    // the last thing we do.
+    model_->OpenDownload();
     return;
   }
 
@@ -550,8 +571,6 @@
     tooltip_text_ = new_tip;
     TooltipTextChanged();
   }
-
-  UpdateAccessibleName();
 }
 
 void DownloadItemView::OnDownloadOpened() {
@@ -569,10 +588,17 @@
       l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, filename_string));
 
   SetEnabled(false);
+  const auto reenable = [](base::WeakPtr<DownloadItemView> view) {
+    if (!view)
+      return;
+    auto* label = view->file_name_label_;
+    label->SetTextStyle(views::style::STYLE_PRIMARY);
+    label->SetText(view->ElidedFilename());
+    view->SetEnabled(true);
+  };
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(&DownloadItemView::Reenable,
-                     weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(std::move(reenable), weak_ptr_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(3));
 
   // Notify our parent.
@@ -663,15 +689,106 @@
 }
 
 void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
+  // TODO(pkasting): Refactor to simplify.
+
   OnPaintBackground(canvas);
 
-  DrawIcon(canvas);
+  bool use_new_warnings =
+      base::FeatureList::IsEnabled(safe_browsing::kUseNewDownloadWarnings);
+  bool show_warning_icon = mode_ != Mode::kNormal;
+  if (show_warning_icon && !use_new_warnings) {
+    int icon_x =
+        (base::i18n::IsRTL() ? width() - GetWarningIconSize() - kStartPadding
+                             : kStartPadding);
+    int icon_y = (height() - GetWarningIconSize()) / 2;
+    canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y);
+
+    OnPaintBorder(canvas);
+    return;
+  }
+
+  // Paint download progress.
+  DownloadItem::DownloadState state = model_->GetState();
+  int progress_x = base::i18n::IsRTL()
+                       ? width() - kStartPadding - kProgressIndicatorSize
+                       : kStartPadding;
+  int progress_y = (height() - kProgressIndicatorSize) / 2;
+  const gfx::RectF progress_bounds(
+      progress_x, progress_y, kProgressIndicatorSize, kProgressIndicatorSize);
+
+  const gfx::ImageSkia* current_icon = nullptr;
+  IconManager* im = g_browser_process->icon_manager();
+  gfx::Image* image_ptr = im->LookupIconFromFilepath(
+      model_->GetTargetFilePath(), IconLoader::SMALL);
+  if (image_ptr)
+    current_icon = image_ptr->ToImageSkia();
+
+  if (state == DownloadItem::IN_PROGRESS &&
+      !(use_new_warnings && show_warning_icon)) {
+    base::TimeDelta indeterminate_progress_time =
+        indeterminate_progress_time_elapsed_;
+    if (!model_->IsPaused()) {
+      indeterminate_progress_time +=
+          base::TimeTicks::Now() - indeterminate_progress_start_time_;
+    }
+    PaintDownloadProgress(canvas, progress_bounds, indeterminate_progress_time,
+                          model_->PercentComplete());
+  } else if (complete_animation_.is_animating()) {
+    DCHECK_EQ(Mode::kNormal, mode_);
+    // Loop back and forth five times.
+    double start = 0, end = 5;
+    if (model_->GetState() == download::DownloadItem::INTERRUPTED)
+      std::swap(start, end);
+    const double value = gfx::Tween::DoubleValueBetween(
+        complete_animation_.GetCurrentValue(), start, end);
+    const double opacity = std::sin((value + 0.5) * base::kPiDouble) / 2 + 0.5;
+    canvas->SaveLayerAlpha(
+        static_cast<uint8_t>(gfx::Tween::IntValueBetween(opacity, 0, 255)));
+    PaintDownloadProgress(canvas, progress_bounds, base::TimeDelta(), 100);
+    canvas->Restore();
+  } else if (use_new_warnings) {
+    current_icon = &file_icon_;
+  }
+
+  if (current_icon) {
+    // Draw the icon image.
+    int kFiletypeIconOffset =
+        (kProgressIndicatorSize - current_icon->height()) / 2;
+    int icon_x = progress_x + kFiletypeIconOffset;
+    int icon_y = progress_y + kFiletypeIconOffset;
+    cc::PaintFlags flags;
+    // Use an alpha to make the image look disabled.
+    if (!GetEnabled())
+      flags.setAlpha(120);
+    canvas->DrawImageInt(*current_icon, icon_x, icon_y, flags);
+
+    // Overlay the danger icon if appropriate.
+    if (show_warning_icon && use_new_warnings) {
+      int icon_x =
+          (base::i18n::IsRTL() ? width() - GetWarningIconSize() - kStartPadding
+                               : kStartPadding) +
+          kDangerIconOffset;
+      int icon_y = (height() - GetWarningIconSize()) / 2 + kDangerIconOffset;
+      canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y);
+    }
+  }
+
   OnPaintBorder(canvas);
 }
 
 void DownloadItemView::OnThemeChanged() {
   views::View::OnThemeChanged();
-  UpdateColorsFromTheme();
+
+  SkColor background_color =
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_DOWNLOAD_SHELF);
+  file_name_label_->SetBackgroundColor(background_color);
+  status_label_->SetBackgroundColor(background_color);
+
+  shelf_->ConfigureButtonForTheme(open_now_button_);
+  shelf_->ConfigureButtonForTheme(save_button_);
+  shelf_->ConfigureButtonForTheme(discard_button_);
+  shelf_->ConfigureButtonForTheme(scan_button_);
+
   SchedulePaint();
   UpdateDropdownButton();
 }
@@ -695,19 +812,30 @@
 }
 
 void DownloadItemView::UpdateMode(Mode mode) {
-  // TODO(pkasting): Refactor further.
-
   mode_ = mode;
+  UpdateFilePath();
   UpdateLabels();
   UpdateButtons();
 
+  // Update the accessible name to contain the status text, filename, and
+  // warning message (if any). The name will be presented when the download item
+  // receives focus.
+  const base::string16 unelided_filename =
+      model_->GetFileNameToReportUser().LossyDisplayName();
+  accessible_name_ =
+      has_warning_label(mode_)
+          ? warning_label_->GetText()
+          : (status_label_->GetText() + base::char16(' ') + unelided_filename);
+  open_button_->SetAccessibleName(accessible_name_);
+  // Do not fire text changed notifications. Screen readers are notified of
+  // status changes via the accessible alert notifications, and text change
+  // notifications would be redundant.
+
   if (is_download_warning(mode_)) {
     time_download_warning_shown_ = base::Time::Now();
     download::DownloadDangerType danger_type = model_->GetDangerType();
     RecordDangerousDownloadWarningShown(danger_type);
 
-    const base::string16 unelided_filename =
-        model_->GetFileNameToReportUser().LossyDisplayName();
     if (danger_type == download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING) {
       announce_accessible_alert_soon_ = true;
       UpdateAccessibleAlert(
@@ -721,70 +849,36 @@
     }
   } else if (mode_ == Mode::kDeepScanning) {
     UpdateAccessibleAlert(
-        l10n_util::GetStringFUTF16(
-            IDS_DEEP_SCANNING_ACCESSIBLE_ALERT,
-            model_->GetFileNameToReportUser().LossyDisplayName()),
+        l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_ACCESSIBLE_ALERT,
+                                   unelided_filename),
         false);
   } else if (mode_ == Mode::kNormal) {
-    switch (model_->GetState()) {
-      case DownloadItem::IN_PROGRESS:
-        // No need to send accessible alert for "paused", as the button ends
-        // up being refocused in the actual use case, and the name of the
-        // button reports that the download has been paused.
-        // Reset the status counter so that user receives immediate feedback
-        // once the download is resumed.
-        if (!model_->IsPaused())
-          UpdateAccessibleAlert(GetInProgressAccessibleAlertText(), false);
-        model_->IsPaused() ? StopDownloadProgress() : StartDownloadProgress();
-        break;
-      case DownloadItem::INTERRUPTED:
-        model_->GetFileNameToReportUser().LossyDisplayName();
-        UpdateAccessibleAlert(
-            l10n_util::GetStringFUTF16(
-                IDS_DOWNLOAD_FAILED_ACCESSIBLE_ALERT,
-                model_->GetFileNameToReportUser().LossyDisplayName()),
-            true);
-        StopDownloadProgress();
-        complete_animation_ = std::make_unique<gfx::SlideAnimation>(this);
-        complete_animation_->SetSlideDuration(
-            base::TimeDelta::FromMilliseconds(2500));
-        complete_animation_->SetTweenType(gfx::Tween::LINEAR);
-        complete_animation_->Show();
-        break;
-      case DownloadItem::COMPLETE:
-        UpdateAccessibleAlert(
-            l10n_util::GetStringFUTF16(
-                IDS_DOWNLOAD_COMPLETE_ACCESSIBLE_ALERT,
-                model_->GetFileNameToReportUser().LossyDisplayName()),
-            true);
-        StopDownloadProgress();
-        complete_animation_ = std::make_unique<gfx::SlideAnimation>(this);
-        complete_animation_->SetSlideDuration(
-            base::TimeDelta::FromMilliseconds(2500));
-        complete_animation_->SetTweenType(gfx::Tween::LINEAR);
-        complete_animation_->Show();
-        break;
-      case DownloadItem::CANCELLED:
-        UpdateAccessibleAlert(
-            l10n_util::GetStringFUTF16(
-                IDS_DOWNLOAD_CANCELLED_ACCESSIBLE_ALERT,
-                model_->GetFileNameToReportUser().LossyDisplayName()),
-            true);
-        StopDownloadProgress();
-        if (complete_animation_)
-          complete_animation_->Stop();
-        break;
-      default:
-        NOTREACHED();
-    }
+    UpdateAccessibleAlertAndTimersForNormalMode();
   }
 
-  // We need to load the icon now that the download has the real path.
-  LoadIcon();
+  shelf_->InvalidateLayout();
+}
 
-  // Force the shelf to layout again as our size has changed.
-  shelf_->Layout();
-  shelf_->SchedulePaint();
+void DownloadItemView::UpdateFilePath() {
+  const base::FilePath file_path = model_->GetTargetFilePath();
+  if (file_path_ == file_path)
+    return;
+
+  file_path_ = file_path;
+  cancelable_task_tracker_.TryCancelAll();
+
+  // The small icon is not stored directly, but will be requested in other
+  // functions, so ask the icon manager to load it so it's cached.
+  IconManager* const im = g_browser_process->icon_manager();
+  im->LoadIcon(file_path_, IconLoader::SMALL,
+               base::BindOnce(&DownloadItemView::OnFileIconLoaded,
+                              base::Unretained(this), IconLoader::SMALL),
+               &cancelable_task_tracker_);
+
+  im->LoadIcon(file_path_, IconLoader::NORMAL,
+               base::BindOnce(&DownloadItemView::OnFileIconLoaded,
+                              base::Unretained(this), IconLoader::NORMAL),
+               &cancelable_task_tracker_);
 }
 
 void DownloadItemView::UpdateLabels() {
@@ -856,346 +950,47 @@
   dropdown_button_->SetVisible(mode_ != Mode::kDangerous);
 }
 
-void DownloadItemView::OpenDownload() {
-  DCHECK(!is_download_warning(mode_));
-  // We're interested in how long it takes users to open downloads.  If they
-  // open downloads super quickly, we should be concerned about clickjacking.
-  UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
-                           base::Time::Now() - creation_time_);
+void DownloadItemView::UpdateAccessibleAlertAndTimersForNormalMode() {
+  using State = download::DownloadItem::DownloadState;
+  const State state = model_->GetState();
+  if ((state == State::IN_PROGRESS) && !model_->IsPaused()) {
+    UpdateAccessibleAlert(GetInProgressAccessibleAlertText(), false);
 
-  // If this is still around for the next status update, it will be read.
-  announce_accessible_alert_soon_ = true;
-
-  // Calling download()->OpenDownload may delete this, so this must be
-  // the last thing we do.
-  model_->OpenDownload();
-}
-
-bool DownloadItemView::SubmitDownloadToFeedbackService(
-    DownloadCommands::Command download_command) {
-#if BUILDFLAG(FULL_SAFE_BROWSING)
-  safe_browsing::SafeBrowsingService* sb_service =
-      g_browser_process->safe_browsing_service();
-  if (!sb_service)
-    return false;
-  safe_browsing::DownloadProtectionService* download_protection_service =
-      sb_service->download_protection_service();
-  if (!download_protection_service)
-    return false;
-  // TODO(shaktisahu): Enable feedback service for offline item.
-  if (model_->download()) {
-    return download_protection_service->MaybeBeginFeedbackForDownload(
-        shelf_->browser()->profile(), model_->download(), download_command);
-  }
-  // WARNING: we are deleted at this point.  Don't access 'this'.
-  return true;
-#else
-  NOTREACHED();
-  return false;
-#endif
-}
-
-void DownloadItemView::DrawIcon(gfx::Canvas* canvas) {
-  bool use_new_warnings =
-      base::FeatureList::IsEnabled(safe_browsing::kUseNewDownloadWarnings);
-  bool show_warning_icon = mode_ != Mode::kNormal;
-  if (show_warning_icon && !use_new_warnings) {
-    int icon_x =
-        (base::i18n::IsRTL() ? width() - GetWarningIconSize() - kStartPadding
-                             : kStartPadding);
-    int icon_y = (height() - GetWarningIconSize()) / 2;
-    canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y);
+    if (!indeterminate_progress_timer_.IsRunning()) {
+      indeterminate_progress_start_time_ = base::TimeTicks::Now();
+      indeterminate_progress_timer_.Reset();
+    }
     return;
   }
 
-  // Paint download progress.
-  DownloadItem::DownloadState state = model_->GetState();
-  int progress_x = base::i18n::IsRTL()
-                       ? width() - kStartPadding - kProgressIndicatorSize
-                       : kStartPadding;
-  int progress_y = (height() - kProgressIndicatorSize) / 2;
-  const gfx::RectF progress_bounds(
-      progress_x, progress_y, kProgressIndicatorSize, kProgressIndicatorSize);
+  if (state != State::IN_PROGRESS) {
+    if (state == State::CANCELLED) {
+      complete_animation_.Stop();
+    } else {
+      complete_animation_.Reset();
+      complete_animation_.Show();
+    }
 
-  const gfx::ImageSkia* current_icon = nullptr;
-  IconManager* im = g_browser_process->icon_manager();
-  gfx::Image* image_ptr = im->LookupIconFromFilepath(
-      model_->GetTargetFilePath(), IconLoader::SMALL);
-  if (image_ptr)
-    current_icon = image_ptr->ToImageSkia();
-
-  if (state == DownloadItem::IN_PROGRESS &&
-      !(use_new_warnings && show_warning_icon)) {
-    base::TimeDelta progress_time = previous_progress_elapsed_;
-    if (!model_->IsPaused())
-      progress_time += base::TimeTicks::Now() - progress_start_time_;
-    PaintDownloadProgress(canvas, progress_bounds, progress_time,
-                          model_->PercentComplete());
-  } else if (complete_animation_.get() && complete_animation_->is_animating()) {
-    DCHECK_EQ(Mode::kNormal, mode_);
-    // Loop back and forth five times.
-    double start = 0, end = 5;
-    if (model_->GetState() == download::DownloadItem::INTERRUPTED)
-      std::swap(start, end);
-    const double value = gfx::Tween::DoubleValueBetween(
-        complete_animation_->GetCurrentValue(), start, end);
-    const double opacity = std::sin((value + 0.5) * base::kPiDouble) / 2 + 0.5;
-    canvas->SaveLayerAlpha(
-        static_cast<uint8_t>(gfx::Tween::IntValueBetween(opacity, 0, 255)));
-    PaintDownloadProgress(canvas, progress_bounds, base::TimeDelta(), 100);
-    canvas->Restore();
-  } else if (use_new_warnings) {
-    current_icon = &icon_;
+    // Send accessible alert since the download has terminated. No need to alert
+    // for "in progress but paused", as the button ends up being refocused in
+    // the actual use case, and the name of the button reports that the download
+    // has been paused.
+    static const base::NoDestructor<base::flat_map<State, int>> kMap({
+        {State::INTERRUPTED, IDS_DOWNLOAD_FAILED_ACCESSIBLE_ALERT},
+        {State::COMPLETE, IDS_DOWNLOAD_COMPLETE_ACCESSIBLE_ALERT},
+        {State::CANCELLED, IDS_DOWNLOAD_CANCELLED_ACCESSIBLE_ALERT},
+    });
+    const base::string16 alert_text = l10n_util::GetStringFUTF16(
+        kMap->at(state), model_->GetFileNameToReportUser().LossyDisplayName());
+    UpdateAccessibleAlert(alert_text, true);
   }
 
-  if (!current_icon)
-    return;
-
-  // Draw the icon image.
-  int kFiletypeIconOffset =
-      (kProgressIndicatorSize - current_icon->height()) / 2;
-  int icon_x = progress_x + kFiletypeIconOffset;
-  int icon_y = progress_y + kFiletypeIconOffset;
-  cc::PaintFlags flags;
-  // Use an alpha to make the image look disabled.
-  if (!GetEnabled())
-    flags.setAlpha(120);
-  canvas->DrawImageInt(*current_icon, icon_x, icon_y, flags);
-
-  // Overlay the danger icon if appropriate.
-  if (show_warning_icon && use_new_warnings) {
-    int icon_x =
-        (base::i18n::IsRTL() ? width() - GetWarningIconSize() - kStartPadding
-                             : kStartPadding) +
-        kDangerIconOffset;
-    int icon_y = (height() - GetWarningIconSize()) / 2 + kDangerIconOffset;
-    canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y);
-  }
-}
-
-void DownloadItemView::LoadIcon() {
-  const base::FilePath last_download_item_path = model_->GetTargetFilePath();
-  if (last_download_item_path_ == last_download_item_path)
-    return;
-
-  last_download_item_path_ = last_download_item_path;
-
-  IconManager* im = g_browser_process->icon_manager();
-  im->LoadIcon(
-      last_download_item_path_, IconLoader::SMALL,
-      base::BindOnce(&DownloadItemView::OnExtractIconComplete,
-                     base::Unretained(this), IconLoader::IconSize::SMALL),
-      &cancelable_task_tracker_);
-  im->LoadIcon(last_download_item_path_, IconLoader::NORMAL,
-               base::BindOnce(&DownloadItemView::OnExtractIconComplete,
-                              base::Unretained(this), IconLoader::NORMAL),
-               &cancelable_task_tracker_);
-}
-
-void DownloadItemView::UpdateColorsFromTheme() {
-  if (!GetThemeProvider())
-    return;
-
-  SkColor background_color =
-      GetThemeProvider()->GetColor(ThemeProperties::COLOR_DOWNLOAD_SHELF);
-  file_name_label_->SetBackgroundColor(background_color);
-  status_label_->SetBackgroundColor(background_color);
-
-  shelf_->ConfigureButtonForTheme(open_now_button_);
-  shelf_->ConfigureButtonForTheme(save_button_);
-  shelf_->ConfigureButtonForTheme(discard_button_);
-  shelf_->ConfigureButtonForTheme(scan_button_);
-}
-
-void DownloadItemView::UpdateDropdownButton() {
-  views::SetImageFromVectorIcon(
-      dropdown_button_,
-      dropdown_state_ == PUSHED ? kCaretDownIcon : kCaretUpIcon,
-      GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
-}
-
-void DownloadItemView::ShowContextMenuImpl(const gfx::Rect& rect,
-                                           ui::MenuSourceType source_type) {
-  // Similar hack as in MenuButton.
-  // We're about to show the menu from a mouse press. By showing from the
-  // mouse press event we block RootView in mouse dispatching. This also
-  // appears to cause RootView to get a mouse pressed BEFORE the mouse
-  // release is seen, which means RootView sends us another mouse press no
-  // matter where the user pressed. To force RootView to recalculate the
-  // mouse target during the mouse press we explicitly set the mouse handler
-  // to null.
-  static_cast<views::internal::RootView*>(GetWidget()->GetRootView())
-      ->SetMouseHandler(nullptr);
-
-  if (!context_menu_.get())
-    context_menu_ = std::make_unique<DownloadShelfContextMenuView>(this);
-  context_menu_->Run(GetWidget()->GetTopLevelWidget(), rect, source_type,
-                     base::Bind(&DownloadItemView::ReleaseDropdown,
-                                weak_ptr_factory_.GetWeakPtr()));
-}
-
-void DownloadItemView::SetDropdownState(State new_state) {
-  if (new_state != dropdown_state_) {
-    dropdown_button_->AnimateInkDrop(new_state == PUSHED
-                                         ? views::InkDropState::ACTIVATED
-                                         : views::InkDropState::DEACTIVATED,
-                                     nullptr);
-    dropdown_state_ = new_state;
-    UpdateDropdownButton();
-    SchedulePaint();
-  }
-}
-
-gfx::ImageSkia DownloadItemView::GetWarningIcon() {
-  switch (model_->GetDangerType()) {
-    case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
-      if (safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile(
-              model()->profile())
-              ->IsUnderAdvancedProtection()) {
-        return gfx::CreateVectorIcon(
-            vector_icons::kErrorIcon, GetErrorIconSize(),
-            GetNativeTheme()->GetSystemColor(
-                ui::NativeTheme::kColorId_AlertSeverityMedium));
-      }
-      FALLTHROUGH;
-
-    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
-    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
-    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
-    case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
-    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
-    case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE:
-    case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED:
-    case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
-      return gfx::CreateVectorIcon(
-          vector_icons::kWarningIcon, GetWarningIconSize(),
-          GetNativeTheme()->GetSystemColor(
-              ui::NativeTheme::kColorId_AlertSeverityHigh));
-
-    case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING:
-    case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
-      return gfx::CreateVectorIcon(
-          vector_icons::kErrorIcon, GetErrorIconSize(),
-          GetNativeTheme()->GetSystemColor(
-              ui::NativeTheme::kColorId_DefaultIconColor));
-
-    case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING:
-      return gfx::CreateVectorIcon(
-          vector_icons::kHelpIcon, GetErrorIconSize(),
-          GetNativeTheme()->GetSystemColor(
-              ui::NativeTheme::kColorId_DefaultIconColor));
-
-    case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
-    case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE:
-    case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
-    case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
-    case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
-    case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
-    case download::DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY:
-    case download::DOWNLOAD_DANGER_TYPE_MAX:
-      break;
-  }
-
-  switch (model_->GetMixedContentStatus()) {
-    case download::DownloadItem::MixedContentStatus::BLOCK:
-      return gfx::CreateVectorIcon(
-          vector_icons::kWarningIcon, GetWarningIconSize(),
-          GetNativeTheme()->GetSystemColor(
-              ui::NativeTheme::kColorId_AlertSeverityHigh));
-    case download::DownloadItem::MixedContentStatus::WARN:
-      return gfx::CreateVectorIcon(
-          vector_icons::kErrorIcon, GetErrorIconSize(),
-          GetNativeTheme()->GetSystemColor(
-              ui::NativeTheme::kColorId_AlertSeverityMedium));
-    case download::DownloadItem::MixedContentStatus::UNKNOWN:
-    case download::DownloadItem::MixedContentStatus::SAFE:
-    case download::DownloadItem::MixedContentStatus::VALIDATED:
-    case download::DownloadItem::MixedContentStatus::SILENT_BLOCK:
-      break;
-  }
-
-  NOTREACHED();
-  return gfx::ImageSkia();
-}
-
-gfx::Size DownloadItemView::GetButtonSize() const {
-  gfx::Size size;
-  if (discard_button_->GetVisible())
-    size.SetToMax(discard_button_->GetPreferredSize());
-  if (save_button_->GetVisible())
-    size.SetToMax(save_button_->GetPreferredSize());
-  if (scan_button_->GetVisible())
-    size.SetToMax(scan_button_->GetPreferredSize());
-  return size;
-}
-
-int DownloadItemView::GetLabelWidth(const views::StyledLabel& label) const {
-  auto lines_for_width = [&label](int width) {
-    return label.GetLayoutSizeInfoForWidth(width).line_sizes.size();
-  };
-
-  // Return 200 if that much width is sufficient to fit |label| on one line.
-  int width = 200;
-  if (lines_for_width(width) < 2)
-    return width;
-
-  // Find an upper bound width sufficient to fit |label| on two lines.
-  int min_width = 1, max_width;
-  for (max_width = width; lines_for_width(max_width) > 2; max_width *= 2)
-    min_width = max_width;
-
-  // Binary-search for the smallest width that fits on two lines.
-  // TODO(pkasting): Can use std::iota_view() when C++20 is available.
-  std::vector<int> widths(max_width + 1 - min_width);
-  std::iota(widths.begin(), widths.end(), min_width);
-  return *util::ranges::lower_bound(widths, 2, util::ranges::greater{},
-                                    std::move(lines_for_width));
-}
-
-void DownloadItemView::Reenable() {
-  file_name_label_->SetTextStyle(views::style::STYLE_PRIMARY);
-  file_name_label_->SetText(ElidedFilename());
-  SetEnabled(true);  // Triggers a repaint.
-}
-
-void DownloadItemView::ReleaseDropdown() {
-  SetDropdownState(NORMAL);
-  // Make sure any new status from activating a context menu option is read.
-  announce_accessible_alert_soon_ = true;
-}
-
-void DownloadItemView::StartDownloadProgress() {
-  if (progress_timer_.IsRunning())
-    return;
-  progress_start_time_ = base::TimeTicks::Now();
-  progress_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(30),
-                        base::Bind(&DownloadItemView::ProgressTimerFired,
-                                   base::Unretained(this)));
-}
-
-void DownloadItemView::StopDownloadProgress() {
   accessible_alert_timer_.AbandonAndStop();
-  if (!progress_timer_.IsRunning())
-    return;
-  previous_progress_elapsed_ += base::TimeTicks::Now() - progress_start_time_;
-  progress_start_time_ = base::TimeTicks();
-  progress_timer_.Stop();
-}
-
-void DownloadItemView::UpdateAccessibleName() {
-  base::string16 new_name;
-  if (has_warning_label(mode_)) {
-    new_name = warning_label_->GetText();
-  } else {
-    new_name = status_label_->GetText() + base::char16(' ') +
-               model_->GetFileNameToReportUser().LossyDisplayName();
+  if (indeterminate_progress_timer_.IsRunning()) {
+    indeterminate_progress_time_elapsed_ +=
+        base::TimeTicks::Now() - indeterminate_progress_start_time_;
+    indeterminate_progress_timer_.Stop();
   }
-
-  // Do not fire text changed notifications. Screen readers are notified of
-  // status changes via the accessible alert notifications, and text change
-  // notifications would be redundant.
-  accessible_name_ = new_name;
-  open_button_->SetAccessibleName(new_name);
 }
 
 void DownloadItemView::UpdateAccessibleAlert(
@@ -1223,10 +1018,8 @@
 
 base::string16 DownloadItemView::GetInProgressAccessibleAlertText() {
   // If opening when complete or there is a warning, use the full status text.
-  if (model_->GetOpenWhenComplete() || has_warning_label(mode_)) {
-    UpdateAccessibleName();
+  if (model_->GetOpenWhenComplete() || has_warning_label(mode_))
     return accessible_name_;
-  }
 
   // Prefer to announce the time remaining, if known.
   base::TimeDelta remaining;
@@ -1262,17 +1055,18 @@
   announce_accessible_alert_soon_ = false;
 }
 
-void DownloadItemView::OnExtractIconComplete(IconLoader::IconSize icon_size,
-                                             gfx::Image icon_bitmap) {
+void DownloadItemView::OnFileIconLoaded(IconLoader::IconSize icon_size,
+                                        gfx::Image icon_bitmap) {
   if (!icon_bitmap.IsEmpty()) {
-    if (icon_size == IconLoader::IconSize::NORMAL) {
+    if (icon_size == IconLoader::NORMAL) {
       // We want a 24x24 icon, but on Windows only 16x16 and 32x32 are
       // available. So take the NORMAL icon and downsize it.
-      icon_ = gfx::ImageSkiaOperations::CreateResizedImage(
+      constexpr gfx::Size kFileIconSize(24, 24);
+      file_icon_ = gfx::ImageSkiaOperations::CreateResizedImage(
           *icon_bitmap.ToImageSkia(), skia::ImageOperations::RESIZE_BEST,
-          gfx::Size(kFileIconSize, kFileIconSize));
+          kFileIconSize);
     }
-    shelf_->SchedulePaint();
+    SchedulePaint();
   }
 }
 
@@ -1313,23 +1107,81 @@
   canvas->DrawPath(progress, progress_flags);
 }
 
-void DownloadItemView::AnimateStateTransition(State from,
-                                              State to,
-                                              gfx::SlideAnimation* animation) {
-  if (from == NORMAL && to == HOT) {
-    animation->Show();
-  } else if (from == HOT && to == NORMAL) {
-    animation->Hide();
-  } else if (from != to) {
-    animation->Reset((to == HOT) ? 1.0 : 0.0);
-  }
-}
+gfx::ImageSkia DownloadItemView::GetWarningIcon() {
+  // TODO(drubery): Replace this with a constexpr variable when the new UX is
+  // fully launched.
+  const int error_icon_size =
+      base::FeatureList::IsEnabled(safe_browsing::kUseNewDownloadWarnings) ? 20
+                                                                           : 27;
+  switch (model_->GetDangerType()) {
+    case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+      if (safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile(
+              model()->profile())
+              ->IsUnderAdvancedProtection()) {
+        return gfx::CreateVectorIcon(
+            vector_icons::kErrorIcon, error_icon_size,
+            GetNativeTheme()->GetSystemColor(
+                ui::NativeTheme::kColorId_AlertSeverityMedium));
+      }
+      FALLTHROUGH;
 
-void DownloadItemView::ProgressTimerFired() {
-  // Only repaint for the indeterminate size case. Otherwise, we'll repaint only
-  // when there's an update notified via OnDownloadUpdated().
-  if (model_->PercentComplete() < 0)
-    SchedulePaint();
+    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
+    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
+    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
+    case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+    case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+    case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE:
+    case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED:
+    case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
+      return gfx::CreateVectorIcon(
+          vector_icons::kWarningIcon, GetWarningIconSize(),
+          GetNativeTheme()->GetSystemColor(
+              ui::NativeTheme::kColorId_AlertSeverityHigh));
+
+    case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING:
+    case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
+      return gfx::CreateVectorIcon(
+          vector_icons::kErrorIcon, error_icon_size,
+          GetNativeTheme()->GetSystemColor(
+              ui::NativeTheme::kColorId_DefaultIconColor));
+
+    case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING:
+      return gfx::CreateVectorIcon(
+          vector_icons::kHelpIcon, error_icon_size,
+          GetNativeTheme()->GetSystemColor(
+              ui::NativeTheme::kColorId_DefaultIconColor));
+
+    case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
+    case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE:
+    case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
+    case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
+    case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
+    case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
+    case download::DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY:
+    case download::DOWNLOAD_DANGER_TYPE_MAX:
+      break;
+  }
+
+  switch (model_->GetMixedContentStatus()) {
+    case download::DownloadItem::MixedContentStatus::BLOCK:
+      return gfx::CreateVectorIcon(
+          vector_icons::kWarningIcon, GetWarningIconSize(),
+          GetNativeTheme()->GetSystemColor(
+              ui::NativeTheme::kColorId_AlertSeverityHigh));
+    case download::DownloadItem::MixedContentStatus::WARN:
+      return gfx::CreateVectorIcon(
+          vector_icons::kErrorIcon, error_icon_size,
+          GetNativeTheme()->GetSystemColor(
+              ui::NativeTheme::kColorId_AlertSeverityMedium));
+    case download::DownloadItem::MixedContentStatus::UNKNOWN:
+    case download::DownloadItem::MixedContentStatus::SAFE:
+    case download::DownloadItem::MixedContentStatus::VALIDATED:
+    case download::DownloadItem::MixedContentStatus::SILENT_BLOCK:
+      break;
+  }
+
+  NOTREACHED();
+  return gfx::ImageSkia();
 }
 
 std::pair<base::string16, int> DownloadItemView::GetStatusTextAndStyle() const {
@@ -1357,16 +1209,118 @@
   return {text, views::style::STYLE_PRIMARY};
 }
 
+gfx::Size DownloadItemView::GetButtonSize() const {
+  gfx::Size size;
+  if (discard_button_->GetVisible())
+    size.SetToMax(discard_button_->GetPreferredSize());
+  if (save_button_->GetVisible())
+    size.SetToMax(save_button_->GetPreferredSize());
+  if (scan_button_->GetVisible())
+    size.SetToMax(scan_button_->GetPreferredSize());
+  return size;
+}
+
 base::string16 DownloadItemView::ElidedFilename() {
   return gfx::ElideFilename(model_->GetFileNameToReportUser(), font_list_,
                             kTextWidth);
 }
 
+int DownloadItemView::GetLabelWidth(const views::StyledLabel& label) const {
+  auto lines_for_width = [&label](int width) {
+    return label.GetLayoutSizeInfoForWidth(width).line_sizes.size();
+  };
+
+  // Return 200 if that much width is sufficient to fit |label| on one line.
+  int width = 200;
+  if (lines_for_width(width) < 2)
+    return width;
+
+  // Find an upper bound width sufficient to fit |label| on two lines.
+  int min_width = 1, max_width;
+  for (max_width = width; lines_for_width(max_width) > 2; max_width *= 2)
+    min_width = max_width;
+
+  // Binary-search for the smallest width that fits on two lines.
+  // TODO(pkasting): Can use std::iota_view() when C++20 is available.
+  std::vector<int> widths(max_width + 1 - min_width);
+  std::iota(widths.begin(), widths.end(), min_width);
+  return *util::ranges::lower_bound(widths, 2, util::ranges::greater{},
+                                    std::move(lines_for_width));
+}
+
+void DownloadItemView::SetDropdownState(State new_state) {
+  if (new_state != dropdown_state_) {
+    dropdown_button_->AnimateInkDrop(new_state == PUSHED
+                                         ? views::InkDropState::ACTIVATED
+                                         : views::InkDropState::DEACTIVATED,
+                                     nullptr);
+    dropdown_state_ = new_state;
+    UpdateDropdownButton();
+    SchedulePaint();
+  }
+}
+
+void DownloadItemView::UpdateDropdownButton() {
+  views::SetImageFromVectorIcon(
+      dropdown_button_,
+      dropdown_state_ == PUSHED ? kCaretDownIcon : kCaretUpIcon,
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
+}
+
+void DownloadItemView::ShowContextMenuImpl(const gfx::Rect& rect,
+                                           ui::MenuSourceType source_type) {
+  // Similar hack as in MenuButtonController.
+  // We're about to show the menu from a mouse press. By showing from the
+  // mouse press event we block RootView in mouse dispatching. This also
+  // appears to cause RootView to get a mouse pressed BEFORE the mouse
+  // release is seen, which means RootView sends us another mouse press no
+  // matter where the user pressed. To force RootView to recalculate the
+  // mouse target during the mouse press we explicitly set the mouse handler
+  // to null.
+  static_cast<views::internal::RootView*>(GetWidget()->GetRootView())
+      ->SetMouseHandler(nullptr);
+
+  if (!context_menu_.get())
+    context_menu_ = std::make_unique<DownloadShelfContextMenuView>(this);
+  const auto release_dropdown = [](DownloadItemView* view) {
+    view->SetDropdownState(NORMAL);
+    // Make sure any new status from activating a context menu option is read.
+    view->announce_accessible_alert_soon_ = true;
+  };
+  context_menu_->Run(
+      GetWidget()->GetTopLevelWidget(), rect, source_type,
+      base::BindRepeating(std::move(release_dropdown), base::Unretained(this)));
+}
+
 void DownloadItemView::OpenDownloadDuringAsyncScanning() {
   model_->CompleteSafeBrowsingScan();
   model_->SetOpenWhenComplete(true);
 }
 
+bool DownloadItemView::SubmitDownloadToFeedbackService(
+    DownloadCommands::Command download_command) {
+#if BUILDFLAG(FULL_SAFE_BROWSING)
+  safe_browsing::SafeBrowsingService* sb_service =
+      g_browser_process->safe_browsing_service();
+  if (!sb_service)
+    return false;
+  safe_browsing::DownloadProtectionService* download_protection_service =
+      sb_service->download_protection_service();
+  if (!download_protection_service)
+    return false;
+  // TODO(shaktisahu): Enable feedback service for offline item.
+  if (model_->download()) {
+    return download_protection_service->MaybeBeginFeedbackForDownload(
+        shelf_->browser()->profile(), model_->download(), download_command);
+  }
+  // WARNING: we are deleted at this point.  Don't access 'this'.
+  return true;
+#else
+  NOTREACHED();
+  return false;
+#endif
+}
+
 // static
 int DownloadItemView::GetWarningIconSize() {
   // TODO(drubery): Replace this method with a constexpr variable when the new
@@ -1376,15 +1330,6 @@
              : 24;
 }
 
-// static
-int DownloadItemView::GetErrorIconSize() {
-  // TODO(drubery): Replace this method with a constexpr variable when the new
-  // UX is fully launched.
-  return base::FeatureList::IsEnabled(safe_browsing::kUseNewDownloadWarnings)
-             ? 20
-             : 27;
-}
-
 void DownloadItemView::ConfirmDeepScanning() {
   DownloadCommands(model_.get()).ExecuteCommand(DownloadCommands::DEEP_SCAN);
 }
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h
index 18ea015..67a3003 100644
--- a/chrome/browser/ui/views/download/download_item_view.h
+++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/tab_modal_confirm_dialog.h"
 #include "components/download/public/common/download_item.h"
 #include "content/public/browser/download_manager.h"
+#include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/font_list.h"
 #include "ui/views/animation/animation_delegate_views.h"
 #include "ui/views/context_menu_controller.h"
@@ -44,7 +45,6 @@
 namespace gfx {
 class Image;
 class ImageSkia;
-class SlideAnimation;
 }
 
 namespace views {
@@ -134,65 +134,19 @@
   // Sets the current mode to |mode| and updates UI appropriately.
   void UpdateMode(Mode mode);
 
+  // Updates the file path, and if necessary, begins loading the file icon in
+  // various sizes. This may eventually result in a callback to
+  // OnFileIconLoaded().
+  void UpdateFilePath();
+
   // Updates the visibility, text, size, etc. of all labels.
   void UpdateLabels();
 
   // Updates the visible and enabled state of all buttons.
   void UpdateButtons();
 
-  void OpenDownload();
-
-  // Submits the downloaded file to the safebrowsing download feedback service.
-  // Returns whether submission was successful. Applies |download_command|, if
-  // submission fails.
-  bool SubmitDownloadToFeedbackService(
-      DownloadCommands::Command download_command);
-
-  void DrawIcon(gfx::Canvas* canvas);
-  void LoadIcon();
-
-  // Update the button colors based on the current theme.
-  void UpdateColorsFromTheme();
-
-  void UpdateDropdownButton();
-
-  // Shows the context menu at the specified location. |point| is in the view's
-  // coordinate system.
-  void ShowContextMenuImpl(const gfx::Rect& rect,
-                           ui::MenuSourceType source_type);
-
-  // Sets the state and triggers a repaint.
-  void SetDropdownState(State new_state);
-
-  // Returns the current warning icon (should only be called when the view is
-  // actually showing a warning).
-  gfx::ImageSkia GetWarningIcon();
-
-  // Sets |size| with the size of the Save and Discard buttons (they have the
-  // same size).
-  gfx::Size GetButtonSize() const;
-
-  // Returns either:
-  //   * 200, if |label| can fit in one line given at most 200 DIP width.
-  //   * The minimum width needed to display |label| on two lines.
-  int GetLabelWidth(const views::StyledLabel& label) const;
-
-  // Reenables the item after it has been disabled when a user clicked it to
-  // open the downloaded file.
-  void Reenable();
-
-  // Releases drop down button after showing a context menu.
-  void ReleaseDropdown();
-
-  // Timer callback for handling animations
-  void StartDownloadProgress();
-  void StopDownloadProgress();
-
-  // Update the accessible name to reflect the current state of the control,
-  // so that screenreaders can access the filename, status text, and
-  // dangerous download warning message (if any). The name will be presented
-  // when the download item receives focus.
-  void UpdateAccessibleName();
+  // Updates the accessible alert and timers for normal mode.
+  void UpdateAccessibleAlertAndTimersForNormalMode();
 
   // Update accessible status text.
   // If |is_last_update| is false, then a timer is used to notify screen readers
@@ -208,7 +162,9 @@
   // reader to speak the current alert immediately.
   void AnnounceAccessibleAlert();
 
-  void OnExtractIconComplete(IconLoader::IconSize icon_size, gfx::Image icon);
+  // Sets |file_icon_| to |icon|. Called when the icon manager has loaded the
+  // normal-size icon for the current file path.
+  void OnFileIconLoaded(IconLoader::IconSize icon_size, gfx::Image icon);
 
   // Paint the common download animation progress foreground and background. If
   // |percent_done| < 0, the total size is indeterminate.
@@ -218,31 +174,48 @@
                              const base::TimeDelta& indeterminate_progress_time,
                              int percent_done) const;
 
-  // Show/Hide/Reset |animation| based on the state transition specified by
-  // |from| and |to|.
-  void AnimateStateTransition(State from,
-                              State to,
-                              gfx::SlideAnimation* animation);
-
-  // Callback for |progress_timer_|.
-  void ProgressTimerFired();
+  // When not in normal mode, returns the current help/warning/error icon.
+  gfx::ImageSkia GetWarningIcon();
 
   // Returns the text and style to use for the status label.
   std::pair<base::string16, int> GetStatusTextAndStyle() const;
 
+  // Returns the size of any button visible next to the label (all visible
+  // buttons are given the same size).
+  gfx::Size GetButtonSize() const;
+
   // Returns the file name to report to user. It might be elided to fit into
   // the text width.
   base::string16 ElidedFilename();
 
+  // Returns either:
+  //   * 200, if |label| can fit in one line given at most 200 DIP width.
+  //   * The minimum width needed to display |label| on two lines.
+  int GetLabelWidth(const views::StyledLabel& label) const;
+
+  // Sets the state and triggers a repaint.
+  void SetDropdownState(State new_state);
+
+  // Sets |dropdown_button_| to have the correct image for the current state.
+  void UpdateDropdownButton();
+
+  // Shows the context menu at the specified location. |point| is in the view's
+  // coordinate system.
+  void ShowContextMenuImpl(const gfx::Rect& rect,
+                           ui::MenuSourceType source_type);
+
   // Opens a file while async scanning is still pending.
   void OpenDownloadDuringAsyncScanning();
 
+  // Submits the downloaded file to the safebrowsing download feedback service.
+  // Applies |download_command| if submission succeeds. Returns whether
+  // submission was successful.
+  bool SubmitDownloadToFeedbackService(
+      DownloadCommands::Command download_command);
+
   // Returns the height/width of the warning icon, in dp.
   static int GetWarningIconSize();
 
-  // Returns the height/width of the error icon, in dp.
-  static int GetErrorIconSize();
-
   // Starts deep scanning for this download item.
   void ConfirmDeepScanning();
 
@@ -270,14 +243,6 @@
   // Mode of the download item view.
   Mode mode_;
 
-  // When download progress last began animating (pausing and resuming will
-  // update this). Used for downloads of unknown size.
-  base::TimeTicks progress_start_time_;
-
-  // Keeps the amount of time spent already animating. Used to keep track of
-  // total active time for downloads of unknown size.
-  base::TimeDelta previous_progress_elapsed_;
-
   // Whether we are dragging the download button.
   bool dragging_;
 
@@ -290,12 +255,6 @@
   // A model class to control the status text we display.
   DownloadUIModel::DownloadUIModelPtr model_;
 
-  // Animation for download complete.
-  std::unique_ptr<gfx::SlideAnimation> complete_animation_;
-
-  // Progress animation
-  base::RepeatingTimer progress_timer_;
-
   // The "open download" button. This button is visually transparent and fills
   // the entire bounds of the DownloadItemView, to make the DownloadItemView
   // itself seem to be clickable while not requiring DownloadItemView itself to
@@ -304,6 +263,8 @@
   // button logic in DownloadItemView.
   views::Button* open_button_;
 
+  gfx::ImageSkia file_icon_;
+
   views::Label* file_name_label_;
   views::Label* status_label_;
   views::StyledLabel* warning_label_;
@@ -324,6 +285,17 @@
   // The currently running download context menu.
   std::unique_ptr<DownloadShelfContextMenuView> context_menu_;
 
+  base::RepeatingTimer indeterminate_progress_timer_;
+
+  // The start of the most recent active period of downloading a file of
+  // indeterminate size.
+  base::TimeTicks indeterminate_progress_start_time_;
+
+  // The total active time downloading a file of indeterminate size.
+  base::TimeDelta indeterminate_progress_time_elapsed_;
+
+  gfx::SlideAnimation complete_animation_{this};
+
   // The name of this view as reported to assistive technology.
   base::string16 accessible_name_;
 
@@ -338,17 +310,13 @@
   // Force the reading of the current alert text the next time it updates.
   bool announce_accessible_alert_soon_;
 
-  // The icon loaded in the download shelf is based on the file path of the
-  // item.  Store the path used, so that we can detect a change in the path
-  // and reload the icon.
-  base::FilePath last_download_item_path_;
+  // |file_icon_| is based on the path of the downloaded item.  Store the path
+  // used, so that we can detect a change in the path and reload the icon.
+  base::FilePath file_path_;
 
   // Deep scanning modal dialog confirming choice to "open now".
   TabModalConfirmDialog* open_now_modal_dialog_;
 
-  // Icon for the download.
-  gfx::ImageSkia icon_;
-
   // Method factory used to delay reenabling of the item when opening the
   // downloaded file.
   base::WeakPtrFactory<DownloadItemView> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
index b7d74d6..78f9a7e 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
@@ -103,6 +103,8 @@
     model_->SetActionVisibility(controller_->GetId(), !IsPinned());
     return;
   } else if (sender->GetID() == EXTENSION_CONTEXT_MENU) {
+    base::RecordAction(base::UserMetricsAction(
+        "Extensions.Toolbar.MoreActionsButtonPressedFromMenu"));
     // TODO(crbug.com/998298): Cleanup the menu source type.
     context_menu_controller_->ShowContextMenuForViewImpl(
         sender, sender->GetMenuPosition(),
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_unittest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_unittest.cc
index 62b7bbe..76fac2a 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view_unittest.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view_unittest.cc
@@ -105,6 +105,8 @@
   ExtensionsMenuItemView* GetOnlyMenuItem();
 
   void ClickPinButton(ExtensionsMenuItemView* menu_item) const;
+  void ClickContextMenuButton(ExtensionsMenuItemView* menu_item) const;
+  void ClickButton(views::Button* button) const;
 
   std::vector<ToolbarActionView*> GetPinnedExtensionViews();
 
@@ -174,15 +176,23 @@
 
 void ExtensionsMenuViewUnitTest::ClickPinButton(
     ExtensionsMenuItemView* menu_item) const {
-  views::ImageButton* pin_button = menu_item->pin_button_for_testing();
+  ClickButton(menu_item->pin_button_for_testing());
+}
+
+void ExtensionsMenuViewUnitTest::ClickContextMenuButton(
+    ExtensionsMenuItemView* menu_item) const {
+  ClickButton(menu_item->context_menu_button_for_testing());
+}
+
+void ExtensionsMenuViewUnitTest::ClickButton(views::Button* button) const {
   ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, gfx::Point(1, 1),
                              gfx::Point(), ui::EventTimeForNow(),
                              ui::EF_LEFT_MOUSE_BUTTON, 0);
-  pin_button->OnMousePressed(press_event);
+  button->OnMousePressed(press_event);
   ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(1, 1),
                                gfx::Point(), ui::EventTimeForNow(),
                                ui::EF_LEFT_MOUSE_BUTTON, 0);
-  pin_button->OnMouseReleased(release_event);
+  button->OnMouseReleased(release_event);
 }
 
 std::vector<ToolbarActionView*>
@@ -518,6 +528,20 @@
   EXPECT_EQ(2, user_action_tester.GetActionCount(kPinButtonUserAction));
 }
 
+TEST_F(ExtensionsMenuViewUnitTest, ContextMenuButtonUserAction) {
+  base::UserActionTester user_action_tester;
+  AddSimpleExtension("Test Extension");
+
+  ExtensionsMenuItemView* menu_item = GetOnlyMenuItem();
+  ASSERT_TRUE(menu_item);
+
+  constexpr char kContextMenuButtonUserAction[] =
+      "Extensions.Toolbar.MoreActionsButtonPressedFromMenu";
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kContextMenuButtonUserAction));
+  ClickContextMenuButton(menu_item);
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kContextMenuButtonUserAction));
+}
+
 // TODO(crbug.com/984654): When supported, add a test to verify the
 // ExtensionsToolbarContainer shrinks when the window is too small to show all
 // pinned extensions.
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
index e835433..5f6d263 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
@@ -105,6 +105,7 @@
 }
 
 void ExtensionsToolbarContainer::UpdateAllIcons() {
+  extensions_button_->UpdateIcon();
   for (const auto& action : actions_)
     action->UpdateState();
 }
diff --git a/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc b/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
index 377938e..ced8dd1 100644
--- a/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
@@ -49,7 +49,7 @@
     // Remove the part of the ImageView that contains the badge.
     SkPath mask;
     mask.addCircle(
-        /*x=*/kBadgedProfilePhotoSize - kBadgeIconSize / 2,
+        /*x=*/GetMirroredXInView(kBadgedProfilePhotoSize - kBadgeIconSize / 2),
         /*y=*/kBadgedProfilePhotoSize - kBadgeIconSize / 2,
         /*radius=*/kBadgeIconSize / 2 + kBadgeBorderWidth);
     mask.toggleInverseFillType();
@@ -190,10 +190,9 @@
 
   from_view = AddChildView(std::move(from_image));
 
-  // TODO(crbug.com/1100814): this arrow will point to the wrong direction in
-  // RTL setup.
   auto arrow_view = std::make_unique<VectorIconView>(
       kBookmarkbarTouchOverflowIcon, kImageSize);
+  arrow_view->EnableCanvasFlippingForRTLUI(true);
   AddChildView(std::move(arrow_view));
 
   to_view = AddChildView(std::move(to_image));
diff --git a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
index 2b869e2..805d847 100644
--- a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
+++ b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
@@ -195,7 +195,7 @@
 
 void PasswordGenerationPopupViewViews::PasswordSelectionUpdated() {
   if (controller_->password_selected())
-    NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
+    NotifyAXSelection(this);
 
   password_view_->UpdateBackground(controller_->password_selected()
                                        ? GetSelectedBackgroundColor()
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
index 29d23c3..02b253b 100644
--- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
+++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
@@ -150,6 +150,7 @@
 
   ShrinkAndHideDisplay(center_error_label_);
   bottom_error_label_->SetVisible(false);
+  download_button_->SetEnabled(true);
   gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(response->bitmap);
   UpdateQRImage(image);
 }
@@ -166,6 +167,7 @@
 }
 
 void QRCodeGeneratorBubble::DisplayError(mojom::QRCodeGeneratorError error) {
+  download_button_->SetEnabled(false);
   if (error == mojom::QRCodeGeneratorError::INPUT_TOO_LONG) {
     ShrinkAndHideDisplay(center_error_label_);
     DisplayPlaceholderImage();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
index f293f92b..a0614d7 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
@@ -17,11 +17,56 @@
 #include "ui/views/layout/animating_layout_manager.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/view_class_properties.h"
+#include "ui/views/view_observer.h"
 
 // static
 const char ToolbarIconContainerView::kToolbarIconContainerViewClassName[] =
     "ToolbarIconContainerView";
 
+// Watches for widget restore (or first show) and resets the animation so icons
+// don't spuriously "animate in" when a window is shown or restored. See
+// crbug.com/1106506 for more details.
+//
+// There is currently no signal that is consistent across platforms and
+// accessible from the View hierarchy that can tell us if, e.g., a window has
+// been restored from a minimized state. While we could theoretically plumb
+// state changes through from NativeWidget, we can observe the specific set of
+// cases we want by observing the size of the window.
+//
+// We *cannot* observe the size of the widget itself, as at least on Windows,
+// minimizing a window does not set the widget to 0x0, but rather a small,
+// Windows 3.1-esque tile (~160x28) and moves it to [-32000, -32000], so far off
+// the screen it can't appear on any monitor.
+//
+// What we can observe is the widget's root view, which is (a) always present
+// after the toolbar has been added to its widget and through its entire
+// lifetime, and (b) is actually set to zero size when the window is zero size
+// or minimized on Windows.
+class ToolbarIconContainerView::WidgetRestoreObserver
+    : public views::ViewObserver {
+ public:
+  explicit WidgetRestoreObserver(
+      ToolbarIconContainerView* toolbar_icon_container_view)
+      : toolbar_icon_container_view_(toolbar_icon_container_view) {
+    scoped_observer_.Add(
+        toolbar_icon_container_view->GetWidget()->GetRootView());
+  }
+
+  void OnViewBoundsChanged(views::View* observed_view) override {
+    const bool is_collapsed = observed_view->bounds().IsEmpty();
+    if (is_collapsed != was_collapsed_) {
+      was_collapsed_ = is_collapsed;
+      if (!is_collapsed)
+        toolbar_icon_container_view_->animating_layout_manager()->ResetLayout();
+    }
+  }
+
+ private:
+  bool was_collapsed_ = true;
+  ToolbarIconContainerView* const toolbar_icon_container_view_;
+  ScopedObserver<views::View, views::ViewObserver> scoped_observer_{this};
+};
+
 ToolbarIconContainerView::ToolbarIconContainerView(bool uses_highlight)
     : uses_highlight_(uses_highlight) {
   views::AnimatingLayoutManager* animating_layout =
@@ -128,6 +173,12 @@
   return kToolbarIconContainerViewClassName;
 }
 
+void ToolbarIconContainerView::AddedToWidget() {
+  // Add an observer to reset the animation if the browser window is restored,
+  // preventing spurious animation. (See crbug.com/1106506)
+  restore_observer_ = std::make_unique<WidgetRestoreObserver>(this);
+}
+
 void ToolbarIconContainerView::AnimationProgressed(
     const gfx::Animation* animation) {
   SetHighlightBorder();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
index 0f164760..0f4835e 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
@@ -74,12 +74,14 @@
 
  private:
   friend class ToolbarAccountIconContainerViewBrowserTest;
+  class WidgetRestoreObserver;
 
   // views::View:
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
   gfx::Insets GetInsets() const override;
   const char* GetClassName() const override;
+  void AddedToWidget() override;
 
   // gfx::AnimationDelegate:
   void AnimationProgressed(const gfx::Animation* animation) override;
@@ -108,6 +110,9 @@
   // Fade-in/out animation for the highlight border.
   gfx::SlideAnimation highlight_animation_{this};
 
+  // Tracks when the widget is restored and resets the layout.
+  std::unique_ptr<WidgetRestoreObserver> restore_observer_;
+
   base::ObserverList<Observer> observers_;
 };
 
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc
index 0656675e..8ba549a4 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -33,6 +33,7 @@
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/onc/onc_utils.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"
 #include "chromeos/services/network_health/public/mojom/network_health.mojom.h"
 #include "components/device_event_log/device_event_log.h"
 #include "content/public/browser/browser_context.h"
@@ -372,6 +373,9 @@
       "networkHealthLabel",
       l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_HEALTH));
   localized_strings->SetString(
+      "networkDiagnosticsLabel",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_DIAGNOSTICS));
+  localized_strings->SetString(
       "visibleNetworksLabel",
       l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS));
   localized_strings->SetString(
@@ -500,6 +504,13 @@
       std::move(receiver));
 }
 
+void NetworkUI::BindInterface(
+    mojo::PendingReceiver<
+        network_diagnostics::mojom::NetworkDiagnosticsRoutines> receiver) {
+  network_health::NetworkHealthService::GetInstance()->BindDiagnosticsRemote(
+      std::move(receiver));
+}
+
 WEB_UI_CONTROLLER_TYPE_IMPL(NetworkUI)
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.h b/chrome/browser/ui/webui/chromeos/network_ui.h
index b7bbd7d..1b26204 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.h
+++ b/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h"
+#include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom-forward.h"
 #include "chromeos/services/network_health/public/mojom/network_health.mojom-forward.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/webui/mojo_web_ui_controller.h"
@@ -36,6 +37,12 @@
       mojo::PendingReceiver<network_health::mojom::NetworkHealthService>
           receiver);
 
+  // Instantiates implementation of the mojom::NetworkDiagnosticsRoutines mojo
+  // interface passing the pending receiver that will be bound.
+  void BindInterface(
+      mojo::PendingReceiver<
+          network_diagnostics::mojom::NetworkDiagnosticsRoutines> receiver);
+
  private:
   WEB_UI_CONTROLLER_TYPE_DECL();
 
diff --git a/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
index 138a9a8..f871046 100644
--- a/chrome/browser/ui/webui/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
@@ -257,21 +257,21 @@
   void EnablePolicy(const char* policy_key, policy::PolicyMap& policies) {
     policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
                  policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(true), nullptr);
+                 base::Value(true), nullptr);
   }
   void SetPolicyValue(const char* policy_key,
                       int value,
                       policy::PolicyMap& policies) {
     policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
                  policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(value), nullptr);
+                 base::Value(value), nullptr);
   }
   void SetPolicyValue(const char* policy_key,
                       bool value,
                       policy::PolicyMap& policies) {
     policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
                  policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(value), nullptr);
+                 base::Value(value), nullptr);
   }
   void SetConnectorPolicyValue(const char* policy_key,
                                const std::string& value,
@@ -280,8 +280,7 @@
     EXPECT_TRUE(policy_value.has_value());
     policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
                  policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
-                 std::make_unique<base::Value>(std::move(policy_value.value())),
-                 nullptr);
+                 std::move(policy_value.value()), nullptr);
   }
 
   base::string16 ExtractPathFromDict(const base::Value& data,
diff --git a/chrome/browser/ui/webui/settings/chromeos/people_section.cc b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
index 1b64e46..cd44688e 100644
--- a/chrome/browser/ui/webui/settings/chromeos/people_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
@@ -417,6 +417,8 @@
        IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW},
       {"lockScreenPinOrPassword",
        IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_PASSWORD},
+      {"lockScreenPinAutoSubmit",
+       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT},
       {"lockScreenSetupFingerprintButton",
        IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SETUP_BUTTON},
       {"lockScreenNotificationHide",
@@ -445,6 +447,8 @@
        IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK},
       {"passwordPromptEnterPasswordLock",
        IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK},
+      {"pinAutoSubmitPrompt",
+       IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_AUTOSUBMIT_PROMPT},
       {"passwordPromptEnterPasswordLoginLock",
        IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK},
   };
@@ -453,6 +457,9 @@
   html_source->AddBoolean("quickUnlockEnabled",
                           chromeos::quick_unlock::IsPinEnabled(pref_service));
   html_source->AddBoolean(
+      "quickUnlockPinAutosubmitFeatureEnabled",
+      chromeos::quick_unlock::IsPinAutosubmitFeatureEnabled());
+  html_source->AddBoolean(
       "quickUnlockDisabledByPolicy",
       chromeos::quick_unlock::IsPinDisabledByPolicy(pref_service));
   html_source->AddBoolean("lockScreenNotificationsEnabled",
@@ -552,6 +559,7 @@
        IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CHOOSE_PIN_TITLE},
       {"configurePinConfirmPinTitle",
        IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CONFIRM_PIN_TITLE},
+      {"invalidPin", IDS_SETTINGS_PEOPLE_PIN_PROMPT_INVALID_PIN},
       {"configurePinMismatched", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED},
       {"configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT},
       {"configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG},
diff --git a/chrome/browser/vr/test/gl_test_environment_unittest.cc b/chrome/browser/vr/test/gl_test_environment_unittest.cc
index ee62da2..79564f96 100644
--- a/chrome/browser/vr/test/gl_test_environment_unittest.cc
+++ b/chrome/browser/vr/test/gl_test_environment_unittest.cc
@@ -7,9 +7,18 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/size.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 namespace vr {
 
 TEST(GlTestEnvironmentTest, InitializeAndCleanup) {
+#if defined(OS_WIN)
+  // VR is not supported on Windows 7.
+  if (base::win::GetVersion() <= base::win::Version::WIN7)
+    return;
+#endif
   GlTestEnvironment gl_test_environment(gfx::Size(100, 100));
   EXPECT_NE(gl_test_environment.GetFrameBufferForTesting(), 0u);
   EXPECT_EQ(glGetError(), (GLenum)GL_NO_ERROR);
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc
index b377c73..a4625f8 100644
--- a/chrome/browser/vr/ui_pixeltest.cc
+++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -10,6 +10,10 @@
 #include "components/omnibox/browser/vector_icons.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 namespace vr {
 
 namespace {
@@ -19,6 +23,11 @@
 }  // namespace
 
 TEST_F(UiPixelTest, DrawVrBrowsingMode) {
+#if defined(OS_WIN)
+  // VR is not supported on Windows 7.
+  if (base::win::GetVersion() <= base::win::Version::WIN7)
+    return;
+#endif
   // Set up scene.
   UiInitialState ui_initial_state;
   ui_initial_state.in_web_vr = false;
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index e2f3897..b500ae5 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -579,7 +579,7 @@
 
 #if defined(OS_WIN)
 const base::Feature kSafetyCheckChromeCleanerChild{
-    "SafetyCheckChromeCleanerChild", base::FEATURE_DISABLED_BY_DEFAULT};
+    "SafetyCheckChromeCleanerChild", base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
 #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/credential_provider/BUILD.gn b/chrome/credential_provider/BUILD.gn
index d171a35..573ede8 100644
--- a/chrome/credential_provider/BUILD.gn
+++ b/chrome/credential_provider/BUILD.gn
@@ -15,8 +15,15 @@
     rebase_path(target_gen_dir, root_build_dir),
   ]
 
+  if (is_debug) {
+    args += [ "debug" ]
+  } else {
+    args += [ "release" ]
+  }
+
   deps = [
     "//chrome/credential_provider/eventlog:gcp_eventlog_provider",
+    "//chrome/credential_provider/extension:gcpw_extension",
     "//chrome/credential_provider/gaiacp:gaia1_0",
     "//chrome/credential_provider/setup:gcp_setup",
     "//chrome/credential_provider/setup:gcp_sfx",
diff --git a/chrome/credential_provider/build/make_setup.py b/chrome/credential_provider/build/make_setup.py
index 794dd3c..44af509 100755
--- a/chrome/credential_provider/build/make_setup.py
+++ b/chrome/credential_provider/build/make_setup.py
@@ -61,6 +61,38 @@
   return (os.path.join(src_path, r'third_party\lzma_sdk\7zr.exe')
           if sys.platform == 'win32' else '7zr')
 
+def GetCmdLine(command, sz_fn, gcp_7z_fn):
+  """Builds the command line for the given archive.
+
+  Args:
+    command: 7Zip command such as 'u', 'rn'..
+    sz_fn: The executable command to run 7zip.
+    gcp_7z_fn: 7zip file for the archive.
+
+  Returns:
+    Returns the command line for the provided command and 7zip archive. Command
+    needs to be one of the supported 7zip commands.
+  """
+  return [
+      sz_fn,  # Path to 7z executable.
+      command,
+
+      # The follow options are equivalent to -mx9 with bcj2 turned on.
+      # Because //third_party/lzma_sdk is only partial copy of the ful sdk
+      # it does not support all forms of compression.  Make sure to use
+      # compression that is compatible.  These same options are used when
+      # building the chrome install compressed files.
+      '-m0=BCJ2',
+      '-m1=LZMA:d27:fb128',
+      '-m2=LZMA:d22:fb128:mf=bt2',
+      '-m3=LZMA:d22:fb128:mf=bt2',
+      '-mb0:1',
+      '-mb0s1:2',
+      '-mb0s2:3',
+
+      # Full path to archive.
+      gcp_7z_fn,
+  ]
 
 def main():
   parser = argparse.ArgumentParser(
@@ -70,6 +102,8 @@
                       help='Path to the credential provider directory')
   parser.add_argument('root_build_path', help='$root_build_dir GN variable')
   parser.add_argument('target_gen_path', help='$target_gen_dir GN variable')
+  parser.add_argument('is_debug', help='$target_gen_dir GN variable')
+
   args = parser.parse_args()
 
   # Make sure all arguments are converted to absolute paths for use below.
@@ -92,43 +126,51 @@
   sfx_fn = os.path.join(args.root_build_path, 'gcp_sfx.exe')
 
   # Build the command line for updating files in the GCP 7z archive.
-  cmd = [
-      sz_fn,  # Path to 7z executable.
-      'u',  # Update file in archive.
+  u_cmd = GetCmdLine('u', sz_fn, gcp_7z_fn)
 
-      # The follow options are equivalent to -mx9 with bcj2 turned on.
-      # Because //third_party/lzma_sdk is only partial copy of the ful sdk
-      # it does not support all forms of compression.  Make sure to use
-      # compression that is compatible.  These same options are used when
-      # building the chrome install compressed files.
-      '-m0=BCJ2',
-      '-m1=LZMA:d27:fb128',
-      '-m2=LZMA:d22:fb128:mf=bt2',
-      '-m3=LZMA:d22:fb128:mf=bt2',
-      '-mb0:1',
-      '-mb0s1:2',
-      '-mb0s2:3',
+  # 7Zip CLI doesn't provide a direct way of adding files into a custom
+  # folder. As suggested by the developer of 7Zip the method is to rename
+  # a file with a specific subfolder to achieve the same.
+  # https://sourceforge.net/p/sevenzip/discussion/45798/thread/5856d980/
+  # For instance, if there is a file called "a.txt" in the parent folder of
+  # archive, when it is renamed with "f\a.txt", the "a.txt" file is actually
+  # placed in a folder called "f".
+  rn_cmd = GetCmdLine('rn', sz_fn, gcp_7z_fn)
 
-      # Full path to archive.
-      gcp_7z_fn,
-  ]
+  # Builds the command line for deleting files in the archive.
+  d_cmd = GetCmdLine('d', sz_fn, gcp_7z_fn)
 
   # Because of the way that 7zS2.sfx determine what program to run after
   # extraction, only gcp_setup.exe should be placed in the root of the archive.
   # Other "executable" type files (bat, cmd, exe, inf, msi, html, htm) should
-  # be located only in subfolders.
+  # be located only in subfolders. That's why all the files initially added in
+  # the top folder. Then the ones need to move to subfolders are renamed. 7z
+  # doesn't have a method to achieve the same directly.
 
-  # Add the credential provider dll and setup programs to the archive.
-  # If the files added to the archive are changed, make sure to update the
-  # kFilenames array in setup_lib.cc.
+  # Add the credential provider dll, credential provider extension and setup
+  # programs to the archive. If the files added to the archive are changed,
+  # make sure to update the kFilenames array in setup_lib.cc.
 
   # 7zip and copy commands don't have a "silent" mode, so redirecting stdout
   # and stderr to nul.
   with open(os.devnull) as nul_file:
     os.chdir(args.root_build_path)
-    subprocess.check_call(cmd + ['gaia1_0.dll'], stdout=nul_file)
-    subprocess.check_call(cmd + ['gcp_setup.exe'], stdout=nul_file)
-    subprocess.check_call(cmd + ['gcp_eventlog_provider.dll'], stdout=nul_file)
+    subprocess.check_call(d_cmd + ['*'], stdout=nul_file)
+    subprocess.check_call(u_cmd + ['gaia1_0.dll'], stdout=nul_file)
+    subprocess.check_call(u_cmd + ['gcp_setup.exe'], stdout=nul_file)
+    subprocess.check_call(u_cmd + ['gcp_eventlog_provider.dll'],
+        stdout=nul_file)
+
+  # GCPW extension is added into gcp_installer.exe only in debug builds to
+  # avoid increasing binary size until the feature is shipped.
+  if args.is_debug == 'debug':
+    with open(os.devnull) as nul_file:
+      subprocess.check_call(u_cmd + ['gcpw_extension.exe'], stdout=nul_file)
+      # Move the executable into a subfolder as there needs to be only one
+      # executable in the parent folder.
+      subprocess.check_call(rn_cmd +
+          ['gcpw_extension.exe', 'extension\gcpw_extension.exe'],
+          stdout=nul_file)
 
   # Combine the SFX module with the archive to make a self extracting
   # executable.
diff --git a/chrome/credential_provider/eventlog/gcp_eventlog_messages.mc b/chrome/credential_provider/eventlog/gcp_eventlog_messages.mc
index 60ddd632..db0d8ac0 100644
--- a/chrome/credential_provider/eventlog/gcp_eventlog_messages.mc
+++ b/chrome/credential_provider/eventlog/gcp_eventlog_messages.mc
Binary files differ
diff --git a/chrome/credential_provider/extension/BUILD.gn b/chrome/credential_provider/extension/BUILD.gn
new file mode 100644
index 0000000..1107eb3
--- /dev/null
+++ b/chrome/credential_provider/extension/BUILD.gn
@@ -0,0 +1,46 @@
+# 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("//build/config/allocator.gni")
+import("//build/config/clang/clang.gni")
+import("//build/config/compiler/compiler.gni")
+import("//build/config/dcheck_always_on.gni")
+import("//build/nocompile.gni")
+import("//chrome/process_version_rc_template.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+import("//testing/test.gni")
+import("//tools/grit/grit_rule.gni")
+
+process_version_rc_template("version") {
+  template_file = "extension.rc.version"
+  output = "$root_out_dir/extension_version.rc"
+}
+
+grit("extension_resources") {
+  source = "extension_resources.grd"
+  inputs = [ "extension_icon.ico" ]
+  outputs = [
+    "grit/extension_resources.h",
+    "grit/extension_resources.rc",
+  ]
+  resource_ids = ""
+  grit_flags = [
+    "-E",
+    "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+  ]
+}
+
+executable("gcpw_extension") {
+  sources = [ "extension_main.cc" ]
+  deps = [
+    ":extension_resources",
+    ":version",
+    "../eventlog:gcp_eventlog_messages",
+    "../gaiacp:common",
+    "//base",
+    "//components/crash/core/app:crash_export_thunks",
+    "//components/crash/core/app:run_as_crashpad_handler",
+  ]
+  configs += [ "//build/config/win:windowed" ]
+}
diff --git a/chrome/credential_provider/extension/extension.rc.version b/chrome/credential_provider/extension/extension.rc.version
new file mode 100644
index 0000000..0a14aba
--- /dev/null
+++ b/chrome/credential_provider/extension/extension.rc.version
@@ -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.

+

+// Use the ordinal 1 here, to avoid needing to #include a header file

+// to use the VS_VERSION_INFO macro. This header file changes with different

+// SDK versions which causes headaches building in some environments. The

+// VERSIONINFO resource will always be at index 1.

+1 VERSIONINFO

+ FILEVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@

+ PRODUCTVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@

+ FILEFLAGSMASK 0x17L

+#ifdef _DEBUG

+ FILEFLAGS 0x1L

+#else

+ FILEFLAGS 0x0L

+#endif

+ FILEOS 0x4L

+ FILETYPE 0x1L

+ FILESUBTYPE 0x0L

+BEGIN

+    BLOCK "StringFileInfo"

+    BEGIN

+        BLOCK "040904b0"

+        BEGIN

+            VALUE "CompanyName", "@COMPANY_FULLNAME@"

+            VALUE "FileDescription", "Google Credential Provider for Windows Extension"

+            VALUE "FileVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"

+            VALUE "InternalName", "gcpw_extension"

+            VALUE "LegalCopyright", "@COPYRIGHT@"

+            VALUE "ProductName", "Google Credential Provider for Windows Extension"

+            VALUE "ProductVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"

+            VALUE "CompanyShortName", "@COMPANY_SHORTNAME@"

+            VALUE "ProductShortName", "GCPW Extension"

+            VALUE "LastChange", "@LASTCHANGE@"

+            VALUE "Official Build", "@OFFICIAL_BUILD@"

+        END

+    END

+    BLOCK "VarFileInfo"

+    BEGIN

+        VALUE "Translation", 0x409, 1200

+    END

+END
\ No newline at end of file
diff --git a/chrome/credential_provider/extension/extension_icon.ico b/chrome/credential_provider/extension/extension_icon.ico
new file mode 100644
index 0000000..7af91ee
--- /dev/null
+++ b/chrome/credential_provider/extension/extension_icon.ico
Binary files differ
diff --git a/chrome/credential_provider/extension/extension_main.cc b/chrome/credential_provider/extension/extension_main.cc
new file mode 100644
index 0000000..df4f706
--- /dev/null
+++ b/chrome/credential_provider/extension/extension_main.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "windows.h"
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/process/memory.h"
+#include "base/win/process_startup_helper.h"
+#include "chrome/credential_provider/eventlog/gcp_eventlog_messages.h"
+#include "chrome/credential_provider/gaiacp/logging.h"
+
+int APIENTRY wWinMain(HINSTANCE hInstance,
+                      HINSTANCE /*hPrevInstance*/,
+                      wchar_t* lpCmdLine,
+                      int /*nCmdShow*/) {
+  base::AtExitManager exit_manager;
+
+  base::CommandLine::Init(0, nullptr);
+  base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
+
+  // Initialize logging.
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_NONE;
+
+  // See if the log file path was specified on the command line.
+  base::FilePath log_file_path = cmdline->GetSwitchValuePath("log-file");
+  if (!log_file_path.empty()) {
+    settings.logging_dest = logging::LOG_TO_FILE;
+    settings.log_file_path = log_file_path.value().c_str();
+  }
+
+  logging::InitLogging(settings);
+  logging::SetLogItems(true,    // Enable process id.
+                       true,    // Enable thread id.
+                       true,    // Enable timestamp.
+                       false);  // Enable tickcount.
+
+  // Make sure the process exits cleanly on unexpected errors.
+  base::EnableTerminationOnHeapCorruption();
+  base::EnableTerminationOnOutOfMemory();
+  base::win::RegisterInvalidParamHandler();
+  base::win::SetupCRT(*base::CommandLine::ForCurrentProcess());
+
+  // Set the event logging source and category for GCPW Extension.
+  logging::SetEventSource("GCPW", GCPW_EXTENSION_CATEGORY, MSG_LOG_MESSAGE);
+
+  LOGFN(VERBOSE) << "GCPW Extension started running.";
+
+  return 0;
+}
diff --git a/chrome/credential_provider/extension/extension_resources.grd b/chrome/credential_provider/extension/extension_resources.grd
new file mode 100644
index 0000000..1ed8ef1
--- /dev/null
+++ b/chrome/credential_provider/extension/extension_resources.grd
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit current_release="1" latest_public_release="0">
+  <outputs>
+    <output filename="grit/extension_resources.h" type="rc_header">
+      <emit emit_type='prepend'></emit>
+    </output>
+    <output filename="grit/extension_resources.rc" type="rc_all" />
+  </outputs>
+  <translations/>
+  <release seq="1">
+    <includes>
+      <include name="IDI_GCP_ICON"
+               file="extension_icon.ico"
+               type="ICON" />
+    </includes>
+  </release>
+</grit>
\ No newline at end of file
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 58d2b230..0517448 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -566,6 +566,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//chrome/android:chrome_all_java",
+      "//chrome/browser/tabmodel:java",
       "//components/crash/android:handler_java",
       "//components/crash/android:java",
       "//components/module_installer/android:module_installer_java",
@@ -3266,6 +3267,7 @@
     "../browser/page_load_metrics/metrics_web_contents_observer_unittest.cc",
     "../browser/page_load_metrics/observers/aborts_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc",
+    "../browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc",
     "../browser/page_load_metrics/observers/amp_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_test_utils.cc",
     "../browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_test_utils.h",
@@ -3621,8 +3623,6 @@
       "../browser/media/feeds/media_feeds_fetcher_unittest.cc",
       "../browser/media/feeds/media_feeds_service_unittest.cc",
       "../browser/media/kaleidoscope/kaleidoscope_switches_unittest.cc",
-      "../browser/nearby_sharing/client/nearby_share_api_call_flow_impl_unittest.cc",
-      "../browser/nearby_sharing/client/nearby_share_client_impl_unittest.cc",
       "../browser/nearby_sharing/fake_nearby_connections_manager.cc",
       "../browser/nearby_sharing/fake_nearby_connections_manager.h",
       "../browser/nearby_sharing/fast_initiation_manager_unittest.cc",
@@ -4340,6 +4340,7 @@
 
     deps += [
       "//chrome/browser/nearby_sharing/certificates:unit_tests",
+      "//chrome/browser/nearby_sharing/client:unit_tests",
       "//chrome/browser/nearby_sharing/logging:unit_tests",
       "//chrome/browser/nearby_sharing/proto",
       "//chrome/browser/nearby_sharing/scheduling:unit_tests",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 66a5360..8e7d700 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -75,7 +75,7 @@
 
   if (!is_java_debug) {
     proguard_enabled = true
-    proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ]
+    proguard_configs = [ "//chrome/android/proguard/apk_for_test.flags" ]
   }
 }
 
@@ -107,7 +107,7 @@
 
   if (!is_java_debug) {
     proguard_enabled = true
-    proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ]
+    proguard_configs = [ "//chrome/android/proguard/apk_for_test.flags" ]
   }
 }
 
@@ -133,7 +133,7 @@
 
   if (!is_java_debug) {
     proguard_enabled = true
-    proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ]
+    proguard_configs = [ "//chrome/android/proguard/apk_for_test.flags" ]
   }
 }
 
@@ -151,7 +151,7 @@
 
   if (!is_java_debug) {
     proguard_enabled = true
-    proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ]
+    proguard_configs = [ "//chrome/android/proguard/apk_for_test.flags" ]
   }
 }
 
diff --git a/chrome/test/data/ads_observer/ad_iframe_writer.js b/chrome/test/data/ads_observer/ad_iframe_writer.js
index 547188d..b49e3a29 100644
--- a/chrome/test/data/ads_observer/ad_iframe_writer.js
+++ b/chrome/test/data/ads_observer/ad_iframe_writer.js
@@ -16,3 +16,19 @@
   document.body.appendChild(frame);
   return frame;
 }
+
+function createAdIframeAtRect(x, y, width, height) {
+  let frame = document.createElement('iframe');
+  frame.style.border = "0px none transparent";
+  frame.style.overflow = "hidden";
+  frame.style.position = "fixed";
+  frame.style.left = x;
+  frame.style.top = y;
+  frame.scrolling = "no";
+  frame.frameborder="0";
+  frame.allowTransparency="true";
+  frame.width = width;
+  frame.height = height;
+  document.body.appendChild(frame);
+  return frame;
+}
diff --git a/chrome/test/data/extensions/subscribe_page_action/src/common.js b/chrome/test/data/extensions/subscribe_page_action/src/common.js
index f52e0b0..f5d60ca 100644
--- a/chrome/test/data/extensions/subscribe_page_action/src/common.js
+++ b/chrome/test/data/extensions/subscribe_page_action/src/common.js
@@ -12,11 +12,20 @@
   // This is the default list, unless replaced by what was saved previously.
   return [
     { 'url': 'http://www.newsblur.com/?url=%s',
-      'description': 'Newsblur'
+      'description': 'Newsblur',
     },
     { 'url': 'http://add.my.yahoo.com/rss?url=%s',
-      'description': 'My Yahoo'
-    }
+      'description': 'My Yahoo',
+    },
+    { 'url': 'http://feedly.com/i/subscription/feed/%s',
+      'description': 'Feedly',
+    },
+    { 'url': 'https://www.inoreader.com/feed/%s',
+      'description': 'Inoreader',
+    },
+    { 'url': 'https://theoldreader.com/feeds/subscribe?url=%s',
+      'description': 'The Old Reader',
+    },
   ];
 }
 
diff --git a/chrome/test/data/extensions/subscribe_page_action/src/manifest.json b/chrome/test/data/extensions/subscribe_page_action/src/manifest.json
index 985212e..643905d 100644
--- a/chrome/test/data/extensions/subscribe_page_action/src/manifest.json
+++ b/chrome/test/data/extensions/subscribe_page_action/src/manifest.json
@@ -25,6 +25,6 @@
     "default_title": "__MSG_rss_subscription_default_title__"
   },
   "permissions": [ "tabs", "http://*/*", "https://*/*", "storage" ],
-  "version": "2.2.5",
+  "version": "2.2.6",
   "web_accessible_resources": [ "iframe.js", "style.css" ]
 }
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 9c63a630..c1966fe 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -5199,6 +5199,8 @@
 
   "ReportDeviceVpdInfo": {},
 
+  "ReportDeviceSystemInfo": {},
+
   "ReportUploadFrequency": {},
 
   "DeviceAllowNewUsers": {},
diff --git a/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js b/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js
index c17c74b..2677b81b 100644
--- a/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js
@@ -19,7 +19,6 @@
 /** @enum {string} */
 destination_dropdown_cros_test.TestNames = {
   CorrectListItems: 'correct list items',
-  ClickRemovesHighlight: 'click removes highlight',
   ClickCloses: 'click closes dropdown',
   TabCloses: 'tab closes dropdown',
   HighlightedAfterUpDown: 'highlighted after keyboard press up and down',
@@ -86,7 +85,7 @@
 
   /** @return {?Element} */
   function getHighlightedElement() {
-    return dropdown.$$('[highlighted_]');
+    return dropdown.$$('.highlighted');
   }
 
   /** @return {string} */
@@ -135,20 +134,6 @@
       });
 
   test(
-      assert(destination_dropdown_cros_test.TestNames.ClickRemovesHighlight),
-      function() {
-        const destinationOne = createDestination('One', DestinationOrigin.CROS);
-        setItemList([destinationOne]);
-        dropdown.value = destinationOne;
-
-        getList()[0].toggleAttribute('highlighted_', true);
-        assertTrue(getList()[0].hasAttribute('highlighted_'));
-
-        getList()[0].click();
-        assertFalse(getList()[0].hasAttribute('highlighted_'));
-      });
-
-  test(
       assert(destination_dropdown_cros_test.TestNames.ClickCloses), function() {
         const destinationOne = createDestination('One', DestinationOrigin.CROS);
         setItemList([destinationOne]);
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
index 795abfd..703bcc3c5 100644
--- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -1142,13 +1142,6 @@
           destination_dropdown_cros_test.TestNames.CorrectListItems);
     });
 
-TEST_F(
-    'PrintPreviewDestinationDropdownCrosTest', 'ClickRemovesHighlight',
-    function() {
-      this.runMochaTest(
-          destination_dropdown_cros_test.TestNames.ClickRemovesHighlight);
-    });
-
 TEST_F('PrintPreviewDestinationDropdownCrosTest', 'ClickCloses', function() {
   this.runMochaTest(destination_dropdown_cros_test.TestNames.ClickCloses);
 });
diff --git a/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js b/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js
index 4ff9757d..b9d0ee8 100644
--- a/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js
+++ b/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js
@@ -30,6 +30,8 @@
     /** @type {!chrome.quickUnlockPrivate.CredentialRequirements} */
     this.credentialRequirements = {minLength: 4, maxLength: 0};
     /** @type {boolean} */ this.lockScreenEnabled = false;
+    /** @type {boolean} */ this.pinAutosubmitEnabled = false;
+    /** @type {boolean} */ this.pinAuthenticationPossible = true;
   }
 
   function clearError_() {
@@ -79,6 +81,38 @@
 
     /**
      * @override
+     * @param {string} token
+     * @param {string} pin
+     * @param {boolean} enabled
+     * @param {function(boolean):void} onComplete
+     */
+    setPinAutosubmitEnabled: function(token, pin, enabled, onComplete) {
+      if (token !== FAKE_TOKEN) {
+        chrome.runtime.lastError = 'Authentication token invalid';
+      } else {
+        this.pinAutosubmitEnabled = enabled && this.credentials[0] === pin;
+        clearError_();
+      }
+
+      if (onComplete) {
+        // Successful if disabling, or enabling with the correct pin.
+        const success = !enabled || this.pinAutosubmitEnabled;
+        onComplete(success);
+      }
+    },
+
+    /**
+     * @override
+     * @param {function(boolean):void} onComplete
+     */
+    canAuthenticatePin: function(onComplete) {
+      if (onComplete) {
+        onComplete(this.pinAuthenticationPossible);
+      }
+    },
+
+    /**
+     * @override
      * @param {function(
      *     !Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void} onComplete
      */
diff --git a/chrome/test/data/webui/settings/chromeos/os_people_page_test.js b/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
index 9b08abe..262b7396 100644
--- a/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
@@ -245,7 +245,12 @@
       const fingerprintTrigger =
           peoplePage.$$('#fingerprint-list').$$('#addFingerprint');
       fingerprintTrigger.click();
-      peoplePage.authToken_ = undefined;
+
+      // Invalidate the auth token by firing an event.
+      assertFalse(peoplePage.authToken_ === undefined);
+      const event = new CustomEvent('invalidate-auth-token-requested');
+      lockScreenPage.dispatchEvent(event);
+      assertTrue(peoplePage.authToken_ === undefined);
 
       assertEquals(
           settings.Router.getInstance().getCurrentRoute(),
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index 9dba5e7..f876f0b 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -1033,6 +1033,11 @@
   }
 
   /** @override */
+  get featureList() {
+    return {enabled: ['features::kQuickUnlockPinAutosubmit']};
+  }
+
+  /** @override */
   get extraLibraries() {
     return super.extraLibraries.concat([
       BROWSER_SETTINGS_PATH + '../fake_chrome_event.js',
@@ -1100,6 +1105,37 @@
 });
 
 // eslint-disable-next-line no-var
+var OSSettingsPeoplePagePinAutosubmitDialogTest =
+    class extends OSSettingsBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return super.browsePreload +
+        'chromeos/os_people_page/pin_autosubmit_dialog.html';
+  }
+
+  /** @override */
+  get featureList() {
+    return {enabled: ['features::kQuickUnlockPinAutosubmit']};
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      BROWSER_SETTINGS_PATH + '../fake_chrome_event.js',
+      BROWSER_SETTINGS_PATH + '../test_util.js',
+      BROWSER_SETTINGS_PATH + 'fake_settings_private.js',
+      'fake_quick_unlock_private.js',
+      'quick_unlock_authenticate_browsertest_chromeos.js'
+    ]);
+  }
+};
+
+TEST_F('OSSettingsPeoplePagePinAutosubmitDialogTest', 'AllJsTests', () => {
+  settings_people_page_quick_unlock.registerAutosubmitDialogTests();
+  mocha.run();
+});
+
+// eslint-disable-next-line no-var
 var OSSettingsPeoplePageSyncControlsTest = class extends OSSettingsBrowserTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
index 4816123..41559f3 100644
--- a/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
+++ b/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
@@ -207,6 +207,7 @@
   function registerLockScreenTests() {
     suite('lock-screen', function() {
       const ENABLE_LOCK_SCREEN_PREF = 'settings.enable_screen_lock';
+      const ENABLE_PIN_AUTOSUBMIT_PREF = 'pin_unlock_autosubmit_enabled';
 
       let fakeSettings = null;
       let passwordRadioButton = null;
@@ -260,6 +261,12 @@
         return isVisible(setupPinButton);
       }
 
+      function isEnablePinAutosubmitToggleVisible() {
+        Polymer.dom.flush();
+        const autosubmitToggle = testElement.$$('#enablePinAutoSubmit');
+        return autosubmitToggle && isVisible(autosubmitToggle);
+      }
+
       setup(function() {
         PolymerTest.clearBody();
 
@@ -276,6 +283,11 @@
             key: 'ash.message_center.lock_screen_mode',
             type: chrome.settingsPrivate.PrefType.STRING,
             value: 'hide'
+          },
+          {
+            key: ENABLE_PIN_AUTOSUBMIT_PREF,
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: false
           }
         ];
         fakeSettings = new settings.FakeSettingsPrivate(fakePrefs);
@@ -445,6 +457,87 @@
             fakeUma.getHistogramValue(
                 settings.LockScreenProgress.CHOOSE_PIN_OR_PASSWORD));
       });
+
+      test('TappingEnableAutoSubmitPinOpensDialog', function() {
+        testElement.authToken = quickUnlockPrivateApi.getFakeToken();
+        // No PIN is set yet.
+        assertFalse(testElement.hasPin);
+        testElement.hasPin = true;
+        // Must be visible when there is a PIN set.
+        assertTrue(isEnablePinAutosubmitToggleVisible());
+
+        getFromElement('#enablePinAutoSubmit').click();
+        Polymer.dom.flush();
+        const autosubmitDialog = getFromElement('#pinAutosubmitDialog');
+        assertTrue(autosubmitDialog.$$('#dialog').open);
+
+        // Cancel button closes the dialog.
+        autosubmitDialog.$$('#cancelButton').click();
+        assertFalse(autosubmitDialog.$$('#dialog').open);
+      });
+    });
+  }
+
+  function registerAutosubmitDialogTests() {
+    suite('autosubmit-dialog', function() {
+      let confirmButton = null;
+      let cancelButton = null;
+      let pinKeyboard = null;
+      let wrongPinDiv = null;
+
+      setup(function() {
+        PolymerTest.clearBody();
+        quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
+
+        // Create auto submit dialog.
+        testElement = document.createElement('settings-pin-autosubmit-dialog');
+        testElement.quickUnlockPrivate = quickUnlockPrivateApi;
+        testElement.authToken = quickUnlockPrivateApi.getFakeToken();
+        document.body.appendChild(testElement);
+        Polymer.dom.flush();
+
+        // Prepare the quick unlock private API.
+        quickUnlockPrivateApi.credentials[0] = '123456';
+        assertFalse(quickUnlockPrivateApi.pinAutosubmitEnabled);
+
+        // Get the elements.
+        pinKeyboard = getFromElement('#pinKeyboard');
+        wrongPinDiv = getFromElement('#invalidPinError');
+        cancelButton = getFromElement('#cancelButton');
+        confirmButton = getFromElement('#confirmButton');
+
+        assertTrue(isVisible(cancelButton));
+        assertTrue(isVisible(confirmButton));
+      });
+
+      test('WrongPinShowsError', function() {
+        assertFalse(isVisible(wrongPinDiv));
+        pinKeyboard.value = '1234';
+        assertFalse(confirmButton.disabled);
+        confirmButton.click();
+        assertFalse(quickUnlockPrivateApi.pinAutosubmitEnabled);
+        assertTrue(isVisible(wrongPinDiv));
+        assertTrue(confirmButton.disabled);
+      });
+
+      test('RightPinActivatesAutosubmit', function() {
+        pinKeyboard.value = '123456';
+        assertFalse(confirmButton.disabled);
+        confirmButton.click();
+        assertTrue(quickUnlockPrivateApi.pinAutosubmitEnabled);
+      });
+
+      // Tests that the dialog fires an event to invalidate the auth token
+      // to trigger a password prompt.
+      test('FireInvalidateTokenRequestWhenPinAuthNotPossible', async () => {
+        // Simulate too many wrong PIN attempts.
+        quickUnlockPrivateApi.pinAuthenticationPossible = false;
+        pinKeyboard.value = '1234';
+        const invalidateTokenEvent = test_util.eventToPromise(
+            'invalidate-auth-token-requested', testElement);
+        confirmButton.click();
+        await invalidateTokenEvent;
+      });
     });
   }
 
@@ -734,6 +827,7 @@
   return {
     registerAuthenticateTests: registerAuthenticateTests,
     registerLockScreenTests: registerLockScreenTests,
+    registerAutosubmitDialogTests: registerAutosubmitDialogTests,
     registerSetupPinDialogTests: registerSetupPinDialogTests
   };
 });
diff --git a/chromecast/media/audio/cast_audio_device_factory.cc b/chromecast/media/audio/cast_audio_device_factory.cc
index 0d106b4..3ca3e601 100644
--- a/chromecast/media/audio/cast_audio_device_factory.cc
+++ b/chromecast/media/audio/cast_audio_device_factory.cc
@@ -78,12 +78,11 @@
 };
 
 scoped_refptr<::media::AudioOutputDevice> NewOutputDevice(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const ::media::AudioSinkParameters& params,
     base::TimeDelta auth_timeout) {
   auto device = base::MakeRefCounted<::media::AudioOutputDevice>(
-      content::AudioOutputIPCFactory::get()->CreateAudioOutputIPC(
-          render_frame_id),
+      content::AudioOutputIPCFactory::get()->CreateAudioOutputIPC(frame_token),
       content::AudioOutputIPCFactory::get()->io_task_runner(), params,
       auth_timeout);
   device->RequestDeviceAuthorization();
@@ -101,7 +100,7 @@
 
 scoped_refptr<::media::AudioRendererSink>
 CastAudioDeviceFactory::CreateFinalAudioRendererSink(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const ::media::AudioSinkParameters& params,
     base::TimeDelta auth_timeout) {
   // Use default implementation.
@@ -111,7 +110,7 @@
 scoped_refptr<::media::AudioRendererSink>
 CastAudioDeviceFactory::CreateAudioRendererSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const ::media::AudioSinkParameters& params) {
   // Use default implementation.
   return nullptr;
@@ -120,15 +119,15 @@
 scoped_refptr<::media::SwitchableAudioRendererSink>
 CastAudioDeviceFactory::CreateSwitchableAudioRendererSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const ::media::AudioSinkParameters& params) {
-  return base::MakeRefCounted<NonSwitchableAudioRendererSink>(NewOutputDevice(
-      render_frame_id, params, base::TimeDelta::FromSeconds(100)));
+  return base::MakeRefCounted<NonSwitchableAudioRendererSink>(
+      NewOutputDevice(frame_token, params, base::TimeDelta::FromSeconds(100)));
 }
 
 scoped_refptr<::media::AudioCapturerSource>
 CastAudioDeviceFactory::CreateAudioCapturerSource(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const ::media::AudioSourceParameters& params) {
   // Use default implementation.
   return nullptr;
diff --git a/chromecast/media/audio/cast_audio_device_factory.h b/chromecast/media/audio/cast_audio_device_factory.h
index e9dfd8f..6ebebbd 100644
--- a/chromecast/media/audio/cast_audio_device_factory.h
+++ b/chromecast/media/audio/cast_audio_device_factory.h
@@ -27,23 +27,23 @@
   ~CastAudioDeviceFactory() final;
 
   scoped_refptr<::media::AudioRendererSink> CreateFinalAudioRendererSink(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const ::media::AudioSinkParameters& params,
       base::TimeDelta auth_timeout) override;
 
   scoped_refptr<::media::AudioRendererSink> CreateAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const ::media::AudioSinkParameters& params) override;
 
   scoped_refptr<::media::SwitchableAudioRendererSink>
   CreateSwitchableAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const ::media::AudioSinkParameters& params) override;
 
   scoped_refptr<::media::AudioCapturerSource> CreateAudioCapturerSource(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const ::media::AudioSourceParameters& params) override;
 
  private:
diff --git a/chromecast/ui/display_settings_manager_impl.cc b/chromecast/ui/display_settings_manager_impl.cc
index 993e307d..2e5f378 100644
--- a/chromecast/ui/display_settings_manager_impl.cc
+++ b/chromecast/ui/display_settings_manager_impl.cc
@@ -24,6 +24,17 @@
 constexpr base::TimeDelta kScreenOnOffDuration =
     base::TimeDelta::FromMilliseconds(200);
 
+#if defined(USE_AURA)
+// These delays are needed to ensure there are no visible artifacts due to the
+// backlight turning on prior to the LCD fully initializing or vice-versa.
+// TODO(b/161140301): Make this configurable for different products
+// TODO(b/161268188): Remove these if the delays can be handled by the kernel
+constexpr base::TimeDelta kDisplayPowerOnDelay =
+    base::TimeDelta::FromMilliseconds(35);
+constexpr base::TimeDelta kDisplayPowerOffDelay =
+    base::TimeDelta::FromMilliseconds(85);
+#endif  // defined(USE_AURA)
+
 const float kMinApiBrightness = 0.0f;
 const float kMaxApiBrightness = 1.0f;
 const float kDefaultApiBrightness = kMaxApiBrightness;
@@ -46,10 +57,14 @@
 #endif  // defined(USE_AURA)
       brightness_(-1.0f),
       screen_on_(true),
+#if defined(USE_AURA)
+      screen_power_on_(true),
+#endif  // defined(USE_AURA)
       color_temperature_animation_(std::make_unique<ColorTemperatureAnimation>(
           window_manager_,
           display_configurator_,
-          color_temperature_config)) {
+          color_temperature_config)),
+      weak_factory_(this) {
   DCHECK(window_manager_);
 #if defined(USE_AURA)
   DCHECK(display_configurator_);
@@ -146,7 +161,68 @@
   SetBrightness(kDefaultApiBrightness);
 }
 
-void DisplaySettingsManagerImpl::SetScreenOn(bool screen_on) {
+#if defined(USE_AURA)
+void DisplaySettingsManagerImpl::OnDisplayOn(bool status) {
+  if (!status) {
+    // Fatal since the user has no other way of turning the screen on if this
+    // failed.
+    LOG(FATAL) << "Failed to enable screen";
+    return;
+  }
+  screen_power_on_ = true;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&DisplaySettingsManagerImpl::OnDisplayOnTimeoutCompleted,
+                     weak_factory_.GetWeakPtr()),
+      kDisplayPowerOnDelay);
+}
+
+void DisplaySettingsManagerImpl::OnDisplayOnTimeoutCompleted() {
+  UpdateBrightness(kScreenOnOffDuration);
+  window_manager_->SetTouchInputDisabled(false /* since screen_on = true */);
+}
+
+void DisplaySettingsManagerImpl::OnDisplayOffTimeoutCompleted() {
+  display_configurator_->DisableDisplay(base::BindOnce([](bool status) {
+    LOG_IF(FATAL, !status) << "Failed to disable display";
+  }));
+  screen_power_on_ = false;
+}
+
+void DisplaySettingsManagerImpl::SetScreenOn(bool screen_on,
+                                             bool display_power) {
+  // Allow this to run if screen_on == screen_on_ == false IF
+  // previously, the screen was turned off without powering off the screen
+  // and we want to power it off this time
+  if (screen_on == screen_on_ &&
+      !(!screen_on && !display_power && screen_power_on_)) {
+    return;
+  }
+
+  LOG(INFO) << "Setting screen on to " << screen_on;
+  screen_on_ = screen_on;
+
+  // TODO(b/161268188): This can be simplified and the delays removed
+  // if backlight timing is handled by the kernel
+  if (screen_on && !screen_power_on_) {
+    display_configurator_->EnableDisplay(base::BindOnce(
+        &DisplaySettingsManagerImpl::OnDisplayOn, weak_factory_.GetWeakPtr()));
+  } else {
+    UpdateBrightness(kScreenOnOffDuration);
+    window_manager_->SetTouchInputDisabled(!screen_on_);
+    if (!screen_on && !display_power) {
+      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+          FROM_HERE,
+          base::BindOnce(
+              &DisplaySettingsManagerImpl::OnDisplayOffTimeoutCompleted,
+              weak_factory_.GetWeakPtr()),
+          kDisplayPowerOffDelay + kScreenOnOffDuration);
+    }
+  }
+}
+#else
+void DisplaySettingsManagerImpl::SetScreenOn(bool screen_on,
+                                             bool display_power) {
   if (screen_on == screen_on_) {
     return;
   }
@@ -157,6 +233,7 @@
   UpdateBrightness(kScreenOnOffDuration);
   window_manager_->SetTouchInputDisabled(!screen_on_);
 }
+#endif
 
 void DisplaySettingsManagerImpl::AddDisplaySettingsObserver(
     mojo::PendingRemote<mojom::DisplaySettingsObserver> observer) {
diff --git a/chromecast/ui/display_settings_manager_impl.h b/chromecast/ui/display_settings_manager_impl.h
index b45a6bb..bd9f545 100644
--- a/chromecast/ui/display_settings_manager_impl.h
+++ b/chromecast/ui/display_settings_manager_impl.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/memory/weak_ptr.h"
 #include "chromecast/ui/display_settings_manager.h"
 #include "chromecast/ui/mojom/display_settings.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -61,7 +62,7 @@
   void SetBrightness(float brightness) override;
   void SetBrightnessSmooth(float brightness, base::TimeDelta duration) override;
   void ResetBrightness() override;
-  void SetScreenOn(bool screen_on) override;
+  void SetScreenOn(bool screen_on, bool display_power) override;
 
  private:
   // mojom::DisplaySettingsObserver implementation
@@ -69,6 +70,11 @@
       mojo::PendingRemote<mojom::DisplaySettingsObserver> observer) override;
 
   void UpdateBrightness(base::TimeDelta duration);
+#if defined(USE_AURA)
+  void OnDisplayOn(bool status);
+  void OnDisplayOnTimeoutCompleted();
+  void OnDisplayOffTimeoutCompleted();
+#endif  // defined(USE_AURA)
 
   CastWindowManager* const window_manager_;
   shell::CastDisplayConfigurator* const display_configurator_;
@@ -79,12 +85,17 @@
 
   float brightness_;
   bool screen_on_;
+#if defined(USE_AURA)
+  bool screen_power_on_;
+#endif  // defined(USE_AURA)
 
   std::unique_ptr<ColorTemperatureAnimation> color_temperature_animation_;
   std::unique_ptr<BrightnessAnimation> brightness_animation_;
 
   mojo::ReceiverSet<mojom::DisplaySettings> receivers_;
   mojo::RemoteSet<mojom::DisplaySettingsObserver> observers_;
+
+  base::WeakPtrFactory<DisplaySettingsManagerImpl> weak_factory_;
 };
 
 }  // namespace chromecast
diff --git a/chromecast/ui/mojom/display_settings.mojom b/chromecast/ui/mojom/display_settings.mojom
index 34ad286..77bb35e 100644
--- a/chromecast/ui/mojom/display_settings.mojom
+++ b/chromecast/ui/mojom/display_settings.mojom
@@ -28,7 +28,10 @@
 
   // Sets whether screen should be on. If set to false, then screen will always
   // be off and other settings will not be applied.
-  SetScreenOn(bool display_on);
+  // |display_on| is false, and |display_power| is false, power off the
+  // display. |display_power| is ignored if |display_on| is true (since
+  // display cannot turn on without display power)
+  SetScreenOn(bool display_on, bool display_power);
 
   // Adds an observer to DisplaySettings.
   AddDisplaySettingsObserver(pending_remote<DisplaySettingsObserver> observer);
diff --git a/chromeos/components/telemetry_extension_ui/probe_service_converters.cc b/chromeos/components/telemetry_extension_ui/probe_service_converters.cc
index 218dc14..6c3bb00 100644
--- a/chromeos/components/telemetry_extension_ui/probe_service_converters.cc
+++ b/chromeos/components/telemetry_extension_ui/probe_service_converters.cc
@@ -24,7 +24,7 @@
     case health::mojom::ProbeCategoryEnum::kNonRemovableBlockDevices:
       return cros_healthd::mojom::ProbeCategoryEnum::kNonRemovableBlockDevices;
     case health::mojom::ProbeCategoryEnum::kCachedVpdData:
-      return cros_healthd::mojom::ProbeCategoryEnum::kCachedVpdData;
+      return cros_healthd::mojom::ProbeCategoryEnum::kSystem;
     case health::mojom::ProbeCategoryEnum::kCpu:
       return cros_healthd::mojom::ProbeCategoryEnum::kCpu;
     case health::mojom::ProbeCategoryEnum::kTimezone:
@@ -114,17 +114,18 @@
 }
 
 health::mojom::CachedVpdInfoPtr UncheckedConvertPtr(
-    cros_healthd::mojom::CachedVpdInfoPtr input) {
-  return health::mojom::CachedVpdInfo::New(std::move(input->sku_number));
+    cros_healthd::mojom::SystemInfoPtr input) {
+  return health::mojom::CachedVpdInfo::New(
+      std::move(input->product_sku_number));
 }
 
 health::mojom::CachedVpdResultPtr UncheckedConvertPtr(
-    cros_healthd::mojom::CachedVpdResultPtr input) {
+    cros_healthd::mojom::SystemResultPtr input) {
   switch (input->which()) {
-    case cros_healthd::mojom::CachedVpdResult::Tag::VPD_INFO:
+    case cros_healthd::mojom::SystemResult::Tag::SYSTEM_INFO:
       return health::mojom::CachedVpdResult::NewVpdInfo(
-          ConvertPtr(std::move(input->get_vpd_info())));
-    case cros_healthd::mojom::CachedVpdResult::Tag::ERROR:
+          ConvertPtr(std::move(input->get_system_info())));
+    case cros_healthd::mojom::SystemResult::Tag::ERROR:
       return health::mojom::CachedVpdResult::NewError(
           ConvertPtr(std::move(input->get_error())));
   }
@@ -303,7 +304,7 @@
   return health::mojom::TelemetryInfo::New(
       ConvertPtr(std::move(input->battery_result)),
       ConvertPtr(std::move(input->block_device_result)),
-      ConvertPtr(std::move(input->vpd_result)),
+      ConvertPtr(std::move(input->system_result)),
       ConvertPtr(std::move(input->cpu_result)),
       ConvertPtr(std::move(input->timezone_result)),
       ConvertPtr(std::move(input->memory_result)),
diff --git a/chromeos/components/telemetry_extension_ui/probe_service_converters.h b/chromeos/components/telemetry_extension_ui/probe_service_converters.h
index 0756eab..504dd98 100644
--- a/chromeos/components/telemetry_extension_ui/probe_service_converters.h
+++ b/chromeos/components/telemetry_extension_ui/probe_service_converters.h
@@ -47,10 +47,10 @@
     cros_healthd::mojom::NonRemovableBlockDeviceResultPtr input);
 
 health::mojom::CachedVpdInfoPtr UncheckedConvertPtr(
-    cros_healthd::mojom::CachedVpdInfoPtr input);
+    cros_healthd::mojom::SystemInfoPtr input);
 
 health::mojom::CachedVpdResultPtr UncheckedConvertPtr(
-    cros_healthd::mojom::CachedVpdResultPtr input);
+    cros_healthd::mojom::SystemResultPtr input);
 
 health::mojom::CpuCStateInfoPtr UncheckedConvertPtr(
     cros_healthd::mojom::CpuCStateInfoPtr input);
diff --git a/chromeos/components/telemetry_extension_ui/probe_service_converters_unittest.cc b/chromeos/components/telemetry_extension_ui/probe_service_converters_unittest.cc
index 1595f6ae..63bb790 100644
--- a/chromeos/components/telemetry_extension_ui/probe_service_converters_unittest.cc
+++ b/chromeos/components/telemetry_extension_ui/probe_service_converters_unittest.cc
@@ -40,7 +40,7 @@
       ElementsAre(
           cros_healthd::mojom::ProbeCategoryEnum::kBattery,
           cros_healthd::mojom::ProbeCategoryEnum::kNonRemovableBlockDevices,
-          cros_healthd::mojom::ProbeCategoryEnum::kCachedVpdData,
+          cros_healthd::mojom::ProbeCategoryEnum::kSystem,
           cros_healthd::mojom::ProbeCategoryEnum::kCpu,
           cros_healthd::mojom::ProbeCategoryEnum::kTimezone,
           cros_healthd::mojom::ProbeCategoryEnum::kMemory,
@@ -244,8 +244,8 @@
 TEST(ProbeServiceConvertors, CachedVpdInfoPtr) {
   constexpr char kSkuNumber[] = "sku-1";
 
-  auto input = cros_healthd::mojom::CachedVpdInfo::New();
-  input->sku_number = kSkuNumber;
+  auto input = cros_healthd::mojom::SystemInfo::New();
+  input->product_sku_number = kSkuNumber;
 
   EXPECT_EQ(ConvertPtr(std::move(input)),
             health::mojom::CachedVpdInfo::New(kSkuNumber));
@@ -253,14 +253,14 @@
 
 TEST(ProbeServiceConvertors, CachedVpdResultPtrInfo) {
   const auto output =
-      ConvertPtr(cros_healthd::mojom::CachedVpdResult::NewVpdInfo(nullptr));
+      ConvertPtr(cros_healthd::mojom::SystemResult::NewSystemInfo(nullptr));
   ASSERT_TRUE(output);
   EXPECT_TRUE(output->is_vpd_info());
 }
 
 TEST(ProbeServiceConvertors, CachedVpdResultPtrError) {
   const auto output =
-      ConvertPtr(cros_healthd::mojom::CachedVpdResult::NewError(nullptr));
+      ConvertPtr(cros_healthd::mojom::SystemResult::NewError(nullptr));
   ASSERT_TRUE(output);
   EXPECT_TRUE(output->is_error());
 }
@@ -636,7 +636,7 @@
     input->battery_result = cros_healthd::mojom::BatteryResult::New();
     input->block_device_result =
         cros_healthd::mojom::NonRemovableBlockDeviceResult::New();
-    input->vpd_result = cros_healthd::mojom::CachedVpdResult::New();
+    input->system_result = cros_healthd::mojom::SystemResult::New();
     input->cpu_result = cros_healthd::mojom::CpuResult::New();
     input->timezone_result = cros_healthd::mojom::TimezoneResult::New();
     input->memory_result = cros_healthd::mojom::MemoryResult::New();
diff --git a/chromeos/network/auto_connect_handler.cc b/chromeos/network/auto_connect_handler.cc
index c5ec216..0fcb6d3 100644
--- a/chromeos/network/auto_connect_handler.cc
+++ b/chromeos/network/auto_connect_handler.cc
@@ -212,7 +212,7 @@
     if (connected_network && !connected_network->IsManagedByPolicy()) {
       network_connection_handler_->ConnectToNetwork(
           managed_network->path(), base::DoNothing(),
-          base::Bind(&ConnectToNetworkErrorCallback), false,
+          base::BindOnce(&ConnectToNetworkErrorCallback), false,
           ConnectCallbackMode::ON_COMPLETED);
       return;
     }
@@ -372,7 +372,7 @@
                  << NetworkPathId(service_path);
   network_connection_handler_->DisconnectNetwork(
       service_path, base::DoNothing(),
-      base::Bind(&DisconnectErrorCallback, service_path));
+      base::BindOnce(&DisconnectErrorCallback, service_path));
 }
 
 void AutoConnectHandler::RemoveNetworkConfigurationForNetwork(
@@ -381,7 +381,7 @@
                  << NetworkPathId(service_path);
   managed_configuration_handler_->RemoveConfiguration(
       service_path, base::DoNothing(),
-      base::Bind(&RemoveNetworkConfigurationErrorCallback));
+      base::BindOnce(&RemoveNetworkConfigurationErrorCallback));
 }
 
 void AutoConnectHandler::DisableAutoconnectForWiFiNetwork(
@@ -393,7 +393,7 @@
                      base::Value(false));
   managed_configuration_handler_->SetProperties(
       service_path, properties, base::DoNothing(),
-      base::Bind(&SetPropertiesErrorCallback));
+      base::BindOnce(&SetPropertiesErrorCallback));
 }
 
 void AutoConnectHandler::CallShillConnectToBestServices() {
diff --git a/chromeos/network/auto_connect_handler_unittest.cc b/chromeos/network/auto_connect_handler_unittest.cc
index ef95109..914fba26 100644
--- a/chromeos/network/auto_connect_handler_unittest.cc
+++ b/chromeos/network/auto_connect_handler_unittest.cc
@@ -79,8 +79,9 @@
 class TestNetworkConnectionHandler : public NetworkConnectionHandler {
  public:
   TestNetworkConnectionHandler(
-      const base::Callback<void(const std::string&)>& disconnect_handler)
-      : NetworkConnectionHandler(), disconnect_handler_(disconnect_handler) {}
+      base::OnceCallback<void(const std::string&)> disconnect_handler)
+      : NetworkConnectionHandler(),
+        disconnect_handler_(std::move(disconnect_handler)) {}
   ~TestNetworkConnectionHandler() override = default;
 
   // NetworkConnectionHandler:
@@ -88,7 +89,7 @@
       const std::string& service_path,
       base::OnceClosure success_callback,
       network_handler::ErrorCallback error_callback) override {
-    disconnect_handler_.Run(service_path);
+    std::move(disconnect_handler_).Run(service_path);
     std::move(success_callback).Run();
   }
 
@@ -104,7 +105,7 @@
                 managed_network_configuration_handler) override {}
 
  private:
-  base::Callback<void(const std::string&)> disconnect_handler_;
+  base::OnceCallback<void(const std::string&)> disconnect_handler_;
 };
 
 }  // namespace
@@ -143,7 +144,7 @@
         nullptr /* prohibited_technologies_handler */);
 
     test_network_connection_handler_.reset(
-        new TestNetworkConnectionHandler(base::Bind(
+        new TestNetworkConnectionHandler(base::BindOnce(
             &AutoConnectHandlerTest::SetDisconnected, base::Unretained(this))));
 
     client_cert_resolver_.reset(new ClientCertResolver());
diff --git a/chromeos/network/fake_network_activation_handler.cc b/chromeos/network/fake_network_activation_handler.cc
index 0da1ba1..77f2eea 100644
--- a/chromeos/network/fake_network_activation_handler.cc
+++ b/chromeos/network/fake_network_activation_handler.cc
@@ -11,10 +11,10 @@
 
 FakeNetworkActivationHandler::ActivationParams::ActivationParams(
     const std::string& service_path,
-    const base::Closure& success_callback,
+    base::OnceClosure success_callback,
     network_handler::ErrorCallback error_callback)
     : service_path_(service_path),
-      success_callback_(success_callback),
+      success_callback_(std::move(success_callback)),
       error_callback_(std::move(error_callback)) {}
 
 FakeNetworkActivationHandler::ActivationParams::ActivationParams(
@@ -22,9 +22,8 @@
 
 FakeNetworkActivationHandler::ActivationParams::~ActivationParams() = default;
 
-void FakeNetworkActivationHandler::ActivationParams::InvokeSuccessCallback()
-    const {
-  success_callback_.Run();
+void FakeNetworkActivationHandler::ActivationParams::InvokeSuccessCallback() {
+  std::move(success_callback_).Run();
 }
 
 void FakeNetworkActivationHandler::ActivationParams::InvokeErrorCallback(
@@ -39,10 +38,10 @@
 
 void FakeNetworkActivationHandler::CompleteActivation(
     const std::string& service_path,
-    const base::Closure& success_callback,
+    base::OnceClosure success_callback,
     network_handler::ErrorCallback error_callback) {
-  complete_activation_calls_.emplace_back(service_path, success_callback,
-                                          std::move(error_callback));
+  complete_activation_calls_.emplace_back(
+      service_path, std::move(success_callback), std::move(error_callback));
 }
 
 }  // namespace chromeos
diff --git a/chromeos/network/fake_network_activation_handler.h b/chromeos/network/fake_network_activation_handler.h
index f68ab66..719e970 100644
--- a/chromeos/network/fake_network_activation_handler.h
+++ b/chromeos/network/fake_network_activation_handler.h
@@ -26,7 +26,7 @@
   class ActivationParams {
    public:
     ActivationParams(const std::string& service_path,
-                     const base::Closure& success_callback,
+                     base::OnceClosure success_callback,
                      network_handler::ErrorCallback error_callback);
 
     ActivationParams(ActivationParams&& other);
@@ -34,13 +34,13 @@
 
     const std::string& service_path() const { return service_path_; }
 
-    void InvokeSuccessCallback() const;
+    void InvokeSuccessCallback();
     void InvokeErrorCallback(const std::string& error_name,
                              std::unique_ptr<base::DictionaryValue> error_data);
 
    private:
     std::string service_path_;
-    base::Closure success_callback_;
+    base::OnceClosure success_callback_;
     network_handler::ErrorCallback error_callback_;
   };
 
@@ -52,7 +52,7 @@
   // NetworkActivationHandler:
   void CompleteActivation(
       const std::string& service_path,
-      const base::Closure& success_callback,
+      base::OnceClosure success_callback,
       network_handler::ErrorCallback error_callback) override;
 
   std::vector<ActivationParams> complete_activation_calls_;
diff --git a/chromeos/network/fake_network_device_handler.cc b/chromeos/network/fake_network_device_handler.cc
index f9a29ca1..2f18ab8 100644
--- a/chromeos/network/fake_network_device_handler.cc
+++ b/chromeos/network/fake_network_device_handler.cc
@@ -18,40 +18,40 @@
     const std::string& device_path,
     const std::string& property_name,
     const base::Value& value,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::RegisterCellularNetwork(
     const std::string& device_path,
     const std::string& network_id,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::RequirePin(
     const std::string& device_path,
     bool require_pin,
     const std::string& pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::EnterPin(
     const std::string& device_path,
     const std::string& pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::UnblockPin(
     const std::string& device_path,
     const std::string& puk,
     const std::string& new_pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::ChangePin(
     const std::string& device_path,
     const std::string& old_pin,
     const std::string& new_pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::SetCellularAllowRoaming(bool allow_roaming) {}
@@ -61,26 +61,26 @@
 
 void FakeNetworkDeviceHandler::AddWifiWakeOnPacketConnection(
     const net::IPEndPoint& ip_endpoint,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::AddWifiWakeOnPacketOfTypes(
     const std::vector<std::string>& types,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::RemoveWifiWakeOnPacketConnection(
     const net::IPEndPoint& ip_endpoint,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::RemoveWifiWakeOnPacketOfTypes(
     const std::vector<std::string>& types,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 void FakeNetworkDeviceHandler::RemoveAllWifiWakeOnPacketConnections(
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {}
 
 }  // namespace chromeos
diff --git a/chromeos/network/fake_network_device_handler.h b/chromeos/network/fake_network_device_handler.h
index a04affc..7f1974c 100644
--- a/chromeos/network/fake_network_device_handler.h
+++ b/chromeos/network/fake_network_device_handler.h
@@ -32,36 +32,36 @@
       const std::string& device_path,
       const std::string& property_name,
       const base::Value& value,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RegisterCellularNetwork(
       const std::string& device_path,
       const std::string& network_id,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RequirePin(const std::string& device_path,
                   bool require_pin,
                   const std::string& pin,
-                  const base::Closure& callback,
+                  base::OnceClosure callback,
                   network_handler::ErrorCallback error_callback) override;
 
   void EnterPin(const std::string& device_path,
                 const std::string& pin,
-                const base::Closure& callback,
+                base::OnceClosure callback,
                 network_handler::ErrorCallback error_callback) override;
 
   void UnblockPin(const std::string& device_path,
                   const std::string& puk,
                   const std::string& new_pin,
-                  const base::Closure& callback,
+                  base::OnceClosure callback,
                   network_handler::ErrorCallback error_callback) override;
 
   void ChangePin(const std::string& device_path,
                  const std::string& old_pin,
                  const std::string& new_pin,
-                 const base::Closure& callback,
+                 base::OnceClosure callback,
                  network_handler::ErrorCallback error_callback) override;
 
   void SetCellularAllowRoaming(bool allow_roaming) override;
@@ -70,26 +70,26 @@
 
   void AddWifiWakeOnPacketConnection(
       const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void AddWifiWakeOnPacketOfTypes(
       const std::vector<std::string>& types,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RemoveWifiWakeOnPacketConnection(
       const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RemoveWifiWakeOnPacketOfTypes(
       const std::vector<std::string>& types,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RemoveAllWifiWakeOnPacketConnections(
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
  private:
diff --git a/chromeos/network/managed_network_configuration_handler.h b/chromeos/network/managed_network_configuration_handler.h
index cab18e0..1d805e5d 100644
--- a/chromeos/network/managed_network_configuration_handler.h
+++ b/chromeos/network/managed_network_configuration_handler.h
@@ -88,7 +88,7 @@
   // properties.
   virtual void SetProperties(const std::string& service_path,
                              const base::DictionaryValue& user_settings,
-                             const base::Closure& callback,
+                             base::OnceClosure callback,
                              network_handler::ErrorCallback error_callback) = 0;
 
   // Initially configures an unconfigured network with the given user settings
@@ -107,7 +107,7 @@
   // configuration will remain. If it was managed, it will still be configured.
   virtual void RemoveConfiguration(
       const std::string& service_path,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) const = 0;
 
   // Removes the user's configuration from the network with |service_path| in
@@ -116,7 +116,7 @@
   // configuration is only removed from a single network profile.
   virtual void RemoveConfigurationFromCurrentProfile(
       const std::string& service_path,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) const = 0;
 
   // Only to be called by NetworkConfigurationUpdater or from tests. Sets
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc
index b75b3408..b867f81 100644
--- a/chromeos/network/managed_network_configuration_handler_impl.cc
+++ b/chromeos/network/managed_network_configuration_handler_impl.cc
@@ -215,7 +215,7 @@
 void ManagedNetworkConfigurationHandlerImpl::SetProperties(
     const std::string& service_path,
     const base::DictionaryValue& user_settings,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const NetworkState* state =
       network_state_handler_->GetNetworkStateFromServicePath(
@@ -305,8 +305,8 @@
           *profile, guid, &policies->global_network_config, network_policy,
           validated_user_settings.get()));
 
-  SetShillProperties(service_path, std::move(shill_dictionary), callback,
-                     std::move(error_callback));
+  SetShillProperties(service_path, std::move(shill_dictionary),
+                     std::move(callback), std::move(error_callback));
 }
 
 void ManagedNetworkConfigurationHandlerImpl::SetManagedActiveProxyValues(
@@ -330,10 +330,11 @@
 void ManagedNetworkConfigurationHandlerImpl::SetShillProperties(
     const std::string& service_path,
     std::unique_ptr<base::DictionaryValue> shill_dictionary,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   network_configuration_handler_->SetShillProperties(
-      service_path, *shill_dictionary, callback, std::move(error_callback));
+      service_path, *shill_dictionary, std::move(callback),
+      std::move(error_callback));
 }
 
 void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration(
@@ -454,19 +455,19 @@
 
 void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration(
     const std::string& service_path,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) const {
   network_configuration_handler_->RemoveConfiguration(
-      service_path, callback, std::move(error_callback));
+      service_path, std::move(callback), std::move(error_callback));
 }
 
 void ManagedNetworkConfigurationHandlerImpl::
     RemoveConfigurationFromCurrentProfile(
         const std::string& service_path,
-        const base::Closure& callback,
+        base::OnceClosure callback,
         network_handler::ErrorCallback error_callback) const {
   network_configuration_handler_->RemoveConfigurationFromCurrentProfile(
-      service_path, callback, std::move(error_callback));
+      service_path, std::move(callback), std::move(error_callback));
 }
 
 void ManagedNetworkConfigurationHandlerImpl::SetPolicy(
diff --git a/chromeos/network/managed_network_configuration_handler_impl.h b/chromeos/network/managed_network_configuration_handler_impl.h
index 597e778e..c521532 100644
--- a/chromeos/network/managed_network_configuration_handler_impl.h
+++ b/chromeos/network/managed_network_configuration_handler_impl.h
@@ -53,7 +53,7 @@
 
   void SetProperties(const std::string& service_path,
                      const base::DictionaryValue& user_settings,
-                     const base::Closure& callback,
+                     base::OnceClosure callback,
                      network_handler::ErrorCallback error_callback) override;
 
   void CreateConfiguration(
@@ -64,12 +64,12 @@
 
   void RemoveConfiguration(
       const std::string& service_path,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) const override;
 
   void RemoveConfigurationFromCurrentProfile(
       const std::string& service_path,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) const override;
 
   void SetPolicy(::onc::ONCSource onc_source,
@@ -196,7 +196,7 @@
   void SetShillProperties(
       const std::string& service_path,
       std::unique_ptr<base::DictionaryValue> shill_dictionary,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback);
 
   // Sets the active proxy values in managed network configurations depending on
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index 4097882..25d13d9b 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -535,7 +535,7 @@
       test_utils::ReadTestDictionary("policy/policy_vpn_ui.json");
   managed_network_configuration_handler_->SetProperties(
       network_state->path(), *ui_config, base::DoNothing(),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   std::string service_path =
@@ -569,7 +569,7 @@
       test_utils::ReadTestDictionary("policy/policy_vpn_ipsec_ui.json");
   managed_network_configuration_handler_->SetProperties(
       network_state->path(), *ui_config, base::DoNothing(),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   // Get shill service properties after the update.
diff --git a/chromeos/network/mock_managed_network_configuration_handler.h b/chromeos/network/mock_managed_network_configuration_handler.h
index 6fd0d527..e106abe 100644
--- a/chromeos/network/mock_managed_network_configuration_handler.h
+++ b/chromeos/network/mock_managed_network_configuration_handler.h
@@ -35,7 +35,7 @@
   MOCK_METHOD4(SetProperties,
                void(const std::string& service_path,
                     const base::DictionaryValue& user_settings,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
   MOCK_CONST_METHOD4(CreateConfiguration,
                      void(const std::string& userhash,
@@ -44,11 +44,11 @@
                           network_handler::ErrorCallback error_callback));
   MOCK_CONST_METHOD3(RemoveConfiguration,
                      void(const std::string& service_path,
-                          const base::Closure& callback,
+                          base::OnceClosure callback,
                           network_handler::ErrorCallback error_callback));
   MOCK_CONST_METHOD3(RemoveConfigurationFromCurrentProfile,
                      void(const std::string& service_path,
-                          const base::Closure& callback,
+                          base::OnceClosure callback,
                           network_handler::ErrorCallback error_callback));
   MOCK_METHOD4(SetPolicy,
                void(::onc::ONCSource onc_source,
diff --git a/chromeos/network/mock_network_device_handler.h b/chromeos/network/mock_network_device_handler.h
index c631bd6..cc032e8 100644
--- a/chromeos/network/mock_network_device_handler.h
+++ b/chromeos/network/mock_network_device_handler.h
@@ -33,40 +33,40 @@
                void(const std::string& device_path,
                     const std::string& property_name,
                     const base::Value& value,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD4(RegisterCellularNetwork,
                void(const std::string& device_path,
                     const std::string& network_id,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD5(RequirePin,
                void(const std::string& device_path,
                     bool require_pin,
                     const std::string& pin,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD4(EnterPin,
                void(const std::string& device_path,
                     const std::string& pin,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD5(UnblockPin,
                void(const std::string& device_path,
                     const std::string& puk,
                     const std::string& new_pin,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD5(ChangePin,
                void(const std::string& device_path,
                     const std::string& old_pin,
                     const std::string& new_pin,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD1(SetCellularAllowRoaming, void(bool allow_roaming));
@@ -78,26 +78,26 @@
 
   MOCK_METHOD3(AddWifiWakeOnPacketConnection,
                void(const net::IPEndPoint& ip_endpoint,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD3(AddWifiWakeOnPacketOfTypes,
                void(const std::vector<std::string>& types,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD3(RemoveWifiWakeOnPacketOfTypes,
                void(const std::vector<std::string>& types,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD3(RemoveWifiWakeOnPacketConnection,
                void(const net::IPEndPoint& ip_endpoint,
-                    const base::Closure& callback,
+                    base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
   MOCK_METHOD2(RemoveAllWifiWakeOnPacketConnections,
-               void(const base::Closure& callback,
+               void(base::OnceClosure callback,
                     network_handler::ErrorCallback error_callback));
 
  private:
diff --git a/chromeos/network/network_activation_handler.h b/chromeos/network/network_activation_handler.h
index b0e529e..9498126 100644
--- a/chromeos/network/network_activation_handler.h
+++ b/chromeos/network/network_activation_handler.h
@@ -27,7 +27,7 @@
   //  kErrorShillError if a DBus or Shill error occurred.
   virtual void CompleteActivation(
       const std::string& service_path,
-      const base::Closure& success_callback,
+      base::OnceClosure success_callback,
       network_handler::ErrorCallback error_callback) = 0;
 
  protected:
diff --git a/chromeos/network/network_activation_handler_impl.cc b/chromeos/network/network_activation_handler_impl.cc
index d92c8a6..d2e9be7 100644
--- a/chromeos/network/network_activation_handler_impl.cc
+++ b/chromeos/network/network_activation_handler_impl.cc
@@ -25,13 +25,13 @@
 
 void NetworkActivationHandlerImpl::CompleteActivation(
     const std::string& service_path,
-    const base::Closure& success_callback,
+    base::OnceClosure success_callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "CompleteActivation: " << NetworkPathId(service_path);
   ShillServiceClient::Get()->CompleteCellularActivation(
       dbus::ObjectPath(service_path),
       base::BindOnce(&NetworkActivationHandlerImpl::HandleShillSuccess,
-                     AsWeakPtr(), success_callback),
+                     AsWeakPtr(), std::move(success_callback)),
       base::BindOnce(&network_handler::ShillErrorCallbackFunction,
                      kErrorShillError, service_path,
                      std::move(error_callback)));
diff --git a/chromeos/network/network_activation_handler_impl.h b/chromeos/network/network_activation_handler_impl.h
index 956c3cf..a2a3cae0 100644
--- a/chromeos/network/network_activation_handler_impl.h
+++ b/chromeos/network/network_activation_handler_impl.h
@@ -27,7 +27,7 @@
   // NetworkActivationHandler:
   void CompleteActivation(
       const std::string& service_path,
-      const base::Closure& success_callback,
+      base::OnceClosure success_callback,
       network_handler::ErrorCallback error_callback) override;
 
  private:
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index 0e8fda4..33b954f4 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -104,12 +104,12 @@
   ProfileEntryDeleter(NetworkConfigurationHandler* handler,
                       const std::string& service_path,
                       const std::string& guid,
-                      const base::Closure& callback,
+                      base::OnceClosure callback,
                       network_handler::ErrorCallback error_callback)
       : owner_(handler),
         service_path_(service_path),
         guid_(guid),
-        callback_(callback),
+        callback_(std::move(callback)),
         error_callback_(std::move(error_callback)) {}
 
   void RestrictToProfilePath(const std::string& profile_path) {
@@ -195,7 +195,7 @@
       return;
     // Run the callback if this is the last pending deletion.
     if (!callback_.is_null())
-      callback_.Run();
+      std::move(callback_).Run();
     // ProfileEntryDeleterCompleted will delete this.
     owner_->ProfileEntryDeleterCompleted(service_path_, guid_,
                                          true /* success */);
@@ -221,7 +221,7 @@
   // value is the profile path of the profile in question.
   std::string restrict_to_profile_path_;
   std::string guid_;
-  base::Closure callback_;
+  base::OnceClosure callback_;
   network_handler::ErrorCallback error_callback_;
 
   // Map of pending profile entry deletions, indexed by profile path.
@@ -271,11 +271,11 @@
 void NetworkConfigurationHandler::SetShillProperties(
     const std::string& service_path,
     const base::DictionaryValue& shill_properties,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   if (shill_properties.empty()) {
     if (!callback.is_null())
-      callback.Run();
+      std::move(callback).Run();
     return;
   }
   NET_LOG(USER) << "SetShillProperties: " << NetworkPathId(service_path);
@@ -304,7 +304,7 @@
       dbus::ObjectPath(service_path), *properties_to_set,
       base::BindOnce(&NetworkConfigurationHandler::SetPropertiesSuccessCallback,
                      weak_ptr_factory_.GetWeakPtr(), service_path,
-                     std::move(properties_copy), callback),
+                     std::move(properties_copy), std::move(callback)),
       base::BindOnce(&NetworkConfigurationHandler::SetPropertiesErrorCallback,
                      weak_ptr_factory_.GetWeakPtr(), service_path,
                      std::move(error_callback)));
@@ -313,11 +313,11 @@
 void NetworkConfigurationHandler::ClearShillProperties(
     const std::string& service_path,
     const std::vector<std::string>& names,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   if (names.empty()) {
     if (!callback.is_null())
-      callback.Run();
+      std::move(callback).Run();
     return;
   }
   NET_LOG(USER) << "ClearShillProperties: " << NetworkPathId(service_path);
@@ -330,7 +330,8 @@
       dbus::ObjectPath(service_path), names,
       base::BindOnce(
           &NetworkConfigurationHandler::ClearPropertiesSuccessCallback,
-          weak_ptr_factory_.GetWeakPtr(), service_path, names, callback),
+          weak_ptr_factory_.GetWeakPtr(), service_path, names,
+          std::move(callback)),
       base::BindOnce(&NetworkConfigurationHandler::ClearPropertiesErrorCallback,
                      weak_ptr_factory_.GetWeakPtr(), service_path,
                      std::move(error_callback)));
@@ -380,15 +381,15 @@
 
 void NetworkConfigurationHandler::RemoveConfiguration(
     const std::string& service_path,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
-  RemoveConfigurationFromProfile(service_path, "", callback,
+  RemoveConfigurationFromProfile(service_path, "", std::move(callback),
                                  std::move(error_callback));
 }
 
 void NetworkConfigurationHandler::RemoveConfigurationFromCurrentProfile(
     const std::string& service_path,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const NetworkState* network_state =
       network_state_handler_->GetNetworkState(service_path);
@@ -399,13 +400,14 @@
     return;
   }
   RemoveConfigurationFromProfile(service_path, network_state->profile_path(),
-                                 callback, std::move(error_callback));
+                                 std::move(callback),
+                                 std::move(error_callback));
 }
 
 void NetworkConfigurationHandler::RemoveConfigurationFromProfile(
     const std::string& service_path,
     const std::string& profile_path,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   // Service.Remove is not reliable. Instead, request the profile entries
   // for the service and remove each entry.
@@ -426,7 +428,7 @@
   for (auto& observer : observers_)
     observer.OnBeforeConfigurationRemoved(service_path, guid);
   ProfileEntryDeleter* deleter = new ProfileEntryDeleter(
-      this, service_path, guid, callback, std::move(error_callback));
+      this, service_path, guid, std::move(callback), std::move(error_callback));
   if (!profile_path.empty())
     deleter->RestrictToProfilePath(profile_path);
   profile_entry_deleters_[service_path] = base::WrapUnique(deleter);
@@ -436,7 +438,7 @@
 void NetworkConfigurationHandler::SetNetworkProfile(
     const std::string& service_path,
     const std::string& profile_path,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "SetNetworkProfile: " << NetworkPathId(service_path) << ": "
                 << profile_path;
@@ -446,7 +448,7 @@
       profile_path_value,
       base::BindOnce(&NetworkConfigurationHandler::SetNetworkProfileCompleted,
                      weak_ptr_factory_.GetWeakPtr(), service_path, profile_path,
-                     callback),
+                     std::move(callback)),
       base::BindOnce(&SetNetworkProfileErrorCallback, service_path,
                      profile_path, std::move(error_callback)));
 }
@@ -566,9 +568,9 @@
 void NetworkConfigurationHandler::SetNetworkProfileCompleted(
     const std::string& service_path,
     const std::string& profile_path,
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   if (!callback.is_null())
-    callback.Run();
+    std::move(callback).Run();
 }
 
 void NetworkConfigurationHandler::GetPropertiesCallback(
@@ -608,9 +610,9 @@
 void NetworkConfigurationHandler::SetPropertiesSuccessCallback(
     const std::string& service_path,
     std::unique_ptr<base::DictionaryValue> set_properties,
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   if (!callback.is_null())
-    callback.Run();
+    std::move(callback).Run();
   const NetworkState* network_state =
       network_state_handler_->GetNetworkState(service_path);
   if (!network_state)
@@ -641,7 +643,7 @@
 void NetworkConfigurationHandler::ClearPropertiesSuccessCallback(
     const std::string& service_path,
     const std::vector<std::string>& names,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     const base::ListValue& result) {
   const std::string kClearPropertiesFailedError("Error.ClearPropertiesFailed");
   DCHECK(names.size() == result.GetSize())
@@ -659,7 +661,7 @@
   }
 
   if (!callback.is_null())
-    callback.Run();
+    std::move(callback).Run();
   network_state_handler_->RequestUpdateForNetwork(service_path);
 }
 
diff --git a/chromeos/network/network_configuration_handler.h b/chromeos/network/network_configuration_handler.h
index 060bd85..ba89af6 100644
--- a/chromeos/network/network_configuration_handler.h
+++ b/chromeos/network/network_configuration_handler.h
@@ -71,7 +71,7 @@
   // clear any existing properties.
   void SetShillProperties(const std::string& service_path,
                           const base::DictionaryValue& shill_properties,
-                          const base::Closure& callback,
+                          base::OnceClosure callback,
                           network_handler::ErrorCallback error_callback);
 
   // Removes the properties with the given property paths. If any of them are
@@ -82,7 +82,7 @@
   // errors, |callback| will be run.
   void ClearShillProperties(const std::string& service_path,
                             const std::vector<std::string>& property_paths,
-                            const base::Closure& callback,
+                            base::OnceClosure callback,
                             network_handler::ErrorCallback error_callback);
 
   // Creates a network with the given |properties| in the specified Shill
@@ -100,20 +100,20 @@
 
   // Removes the network |service_path| from any profiles that include it.
   void RemoveConfiguration(const std::string& service_path,
-                           const base::Closure& callback,
+                           base::OnceClosure callback,
                            network_handler::ErrorCallback error_callback);
 
   // Removes the network |service_path| from the profile that contains its
   // currently active configuration.
   void RemoveConfigurationFromCurrentProfile(
       const std::string& service_path,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback);
 
   // Changes the profile for the network |service_path| to |profile_path|.
   void SetNetworkProfile(const std::string& service_path,
                          const std::string& profile_path,
-                         const base::Closure& callback,
+                         base::OnceClosure callback,
                          network_handler::ErrorCallback error_callback);
 
   // Changes the value of a shill manager property.
@@ -165,7 +165,7 @@
   // Callback after moving a network configuration.
   void SetNetworkProfileCompleted(const std::string& service_path,
                                   const std::string& profile_path,
-                                  const base::Closure& callback);
+                                  base::OnceClosure callback);
 
   // Set the Name and GUID properties correctly and Invoke |callback|.
   void GetPropertiesCallback(network_handler::ResultCallback callback,
@@ -178,7 +178,7 @@
   void SetPropertiesSuccessCallback(
       const std::string& service_path,
       std::unique_ptr<base::DictionaryValue> set_properties,
-      const base::Closure& callback);
+      base::OnceClosure callback);
   void SetPropertiesErrorCallback(const std::string& service_path,
                                   network_handler::ErrorCallback error_callback,
                                   const std::string& dbus_error_name,
@@ -188,7 +188,7 @@
   // for the service after clearing properties.
   void ClearPropertiesSuccessCallback(const std::string& service_path,
                                       const std::vector<std::string>& names,
-                                      const base::Closure& callback,
+                                      base::OnceClosure callback,
                                       const base::ListValue& result);
   void ClearPropertiesErrorCallback(
       const std::string& service_path,
@@ -202,7 +202,7 @@
   void RemoveConfigurationFromProfile(
       const std::string& service_path,
       const std::string& profile_path,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback);
 
   // Unowned associated Network*Handlers (global or test instance).
diff --git a/chromeos/network/network_configuration_handler_unittest.cc b/chromeos/network/network_configuration_handler_unittest.cc
index a12e474..30ca2704 100644
--- a/chromeos/network/network_configuration_handler_unittest.cc
+++ b/chromeos/network/network_configuration_handler_unittest.cc
@@ -249,10 +249,10 @@
 
     network_configuration_handler_->CreateShillConfiguration(
         properties,
-        base::Bind(
+        base::BindOnce(
             &NetworkConfigurationHandlerTest::CreateConfigurationCallback,
             base::Unretained(this)),
-        base::Bind(&ErrorCallback));
+        base::BindOnce(&ErrorCallback));
     base::RunLoop().RunUntilIdle();
   }
 
@@ -441,7 +441,7 @@
   base::DictionaryValue value;
   value.SetString(shill::kSSIDProperty, kNetworkName);
   network_configuration_handler_->SetShillProperties(
-      kServicePath, value, base::DoNothing(), base::Bind(&ErrorCallback));
+      kServicePath, value, base::DoNothing(), base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   const base::DictionaryValue* properties =
@@ -465,7 +465,7 @@
   // Now clear it.
   std::vector<std::string> names = {shill::kSSIDProperty};
   network_configuration_handler_->ClearShillProperties(
-      kServicePath, names, base::DoNothing(), base::Bind(&ErrorCallback));
+      kServicePath, names, base::DoNothing(), base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   const base::DictionaryValue* properties =
@@ -488,7 +488,7 @@
   // the whole ClearShillProperties() should succeed.
   std::vector<std::string> names = {"Unknown name"};
   network_configuration_handler_->ClearShillProperties(
-      kServicePath, names, base::DoNothing(), base::Bind(&ErrorCallback));
+      kServicePath, names, base::DoNothing(), base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 }
 
@@ -506,8 +506,8 @@
   std::string service_path;
   std::string guid;
   network_configuration_handler_->CreateShillConfiguration(
-      value, base::Bind(&CopyServiceResult, &success, &service_path, &guid),
-      base::Bind(&ErrorCallback));
+      value, base::BindOnce(&CopyServiceResult, &success, &service_path, &guid),
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   ASSERT_TRUE(success);
@@ -522,8 +522,8 @@
   TestCallback test_callback;
   network_configuration_handler_->RemoveConfiguration(
       "/service/2",
-      base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&TestCallback::Run, base::Unretained(&test_callback)),
+      base::BindOnce(&ErrorCallback));
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, test_callback.run_count());
@@ -546,8 +546,8 @@
   TestCallback test_callback;
   network_configuration_handler_->RemoveConfigurationFromCurrentProfile(
       "/service/2",
-      base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&TestCallback::Run, base::Unretained(&test_callback)),
+      base::BindOnce(&ErrorCallback));
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, test_callback.run_count());
@@ -572,8 +572,8 @@
   std::string error;
   network_configuration_handler_->RemoveConfigurationFromCurrentProfile(
       "/service/3",
-      base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
-      base::Bind(&RecordError, base::Unretained(&error)));
+      base::BindOnce(&TestCallback::Run, base::Unretained(&test_callback)),
+      base::BindOnce(&RecordError, base::Unretained(&error)));
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, test_callback.run_count());
@@ -596,9 +596,9 @@
   network_configuration_handler_->SetShillProperties(
       service_path, properties_to_set,
 
-      base::Bind(&NetworkConfigurationHandlerTest::SuccessCallback,
-                 base::Unretained(this), "SetProperties"),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&NetworkConfigurationHandlerTest::SuccessCallback,
+                     base::Unretained(this), "SetProperties"),
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ("SetProperties", success_callback_name_);
@@ -618,9 +618,9 @@
   properties_to_clear.push_back(shill::kPassphraseProperty);
   network_configuration_handler_->ClearShillProperties(
       service_path, properties_to_clear,
-      base::Bind(&NetworkConfigurationHandlerTest::SuccessCallback,
-                 base::Unretained(this), "ClearProperties"),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&NetworkConfigurationHandlerTest::SuccessCallback,
+                     base::Unretained(this), "ClearProperties"),
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ("ClearProperties", success_callback_name_);
@@ -643,7 +643,7 @@
   properties_to_set.SetKey(shill::kWifiHexSsid, base::Value(wifi_hex));
   network_configuration_handler_->SetShillProperties(
       service_path, properties_to_set, base::DoNothing(),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
   std::string wifi_hex_result;
   EXPECT_TRUE(GetServiceStringProperty(service_path, shill::kWifiHexSsid,
@@ -713,7 +713,7 @@
           service_path));
 
   network_configuration_handler_->RemoveConfiguration(
-      service_path, base::DoNothing(), base::Bind(&ErrorCallback));
+      service_path, base::DoNothing(), base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(
@@ -744,7 +744,7 @@
 
   network_configuration_handler_->SetShillProperties(
       create_service_path_, properties, base::DoNothing(),
-      base::Bind(&ErrorCallback));
+      base::BindOnce(&ErrorCallback));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(network_configuration_observer->HasUpdatedConfiguration(
diff --git a/chromeos/network/network_connect.cc b/chromeos/network/network_connect.cc
index 9fba44a..3d1dc8b 100644
--- a/chromeos/network/network_connect.cc
+++ b/chromeos/network/network_connect.cc
@@ -213,8 +213,8 @@
       network->path(),
       base::BindOnce(&NetworkConnectImpl::OnConnectSucceeded,
                      weak_factory_.GetWeakPtr(), network_id),
-      base::Bind(&NetworkConnectImpl::OnConnectFailed,
-                 weak_factory_.GetWeakPtr(), network_id),
+      base::BindOnce(&NetworkConnectImpl::OnConnectFailed,
+                     weak_factory_.GetWeakPtr(), network_id),
       check_error_state, ConnectCallbackMode::ON_COMPLETED);
 }
 
@@ -252,10 +252,10 @@
       ->network_configuration_handler()
       ->CreateShillConfiguration(
           *shill_properties,
-          base::Bind(&NetworkConnectImpl::OnConfigureSucceeded,
-                     weak_factory_.GetWeakPtr(), connect_on_configure),
-          base::Bind(&NetworkConnectImpl::OnConfigureFailed,
-                     weak_factory_.GetWeakPtr()));
+          base::BindOnce(&NetworkConnectImpl::OnConfigureSucceeded,
+                         weak_factory_.GetWeakPtr(), connect_on_configure),
+          base::BindOnce(&NetworkConnectImpl::OnConfigureFailed,
+                         weak_factory_.GetWeakPtr()));
 }
 
 void NetworkConnectImpl::SetPropertiesFailed(
@@ -300,10 +300,11 @@
   const bool check_error_state = false;
   NetworkHandler::Get()->network_configuration_handler()->ClearShillProperties(
       network->path(), properties_to_clear,
-      base::Bind(&NetworkConnectImpl::CallConnectToNetwork,
-                 weak_factory_.GetWeakPtr(), network_id, check_error_state),
-      base::Bind(&NetworkConnectImpl::SetPropertiesFailed,
-                 weak_factory_.GetWeakPtr(), "ClearProperties", network_id));
+      base::BindOnce(&NetworkConnectImpl::CallConnectToNetwork,
+                     weak_factory_.GetWeakPtr(), network_id, check_error_state),
+      base::BindOnce(&NetworkConnectImpl::SetPropertiesFailed,
+                     weak_factory_.GetWeakPtr(), "ClearProperties",
+                     network_id));
 }
 
 void NetworkConnectImpl::ConfigureSetProfileSucceeded(
@@ -319,10 +320,11 @@
   }
   NetworkHandler::Get()->network_configuration_handler()->SetShillProperties(
       network->path(), *properties_to_set,
-      base::Bind(&NetworkConnectImpl::ClearPropertiesAndConnect,
-                 weak_factory_.GetWeakPtr(), network_id, properties_to_clear),
-      base::Bind(&NetworkConnectImpl::SetPropertiesFailed,
-                 weak_factory_.GetWeakPtr(), "SetProperties", network_id));
+      base::BindOnce(&NetworkConnectImpl::ClearPropertiesAndConnect,
+                     weak_factory_.GetWeakPtr(), network_id,
+                     properties_to_clear),
+      base::BindOnce(&NetworkConnectImpl::SetPropertiesFailed,
+                     weak_factory_.GetWeakPtr(), "SetProperties", network_id));
 }
 
 // Public methods
@@ -359,7 +361,8 @@
   if (!network)
     return;
   NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
-      network->path(), base::DoNothing(), base::Bind(&IgnoreDisconnectError));
+      network->path(), base::DoNothing(),
+      base::BindOnce(&IgnoreDisconnectError));
 }
 
 void NetworkConnectImpl::SetTechnologyEnabled(
@@ -463,12 +466,12 @@
   }
   NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
       network->path(), profile_path,
-      base::Bind(&NetworkConnectImpl::ConfigureSetProfileSucceeded,
-                 weak_factory_.GetWeakPtr(), network_id,
-                 base::Passed(&properties_to_set)),
-      base::Bind(&NetworkConnectImpl::SetPropertiesFailed,
-                 weak_factory_.GetWeakPtr(), "SetProfile: " + profile_path,
-                 network_id));
+      base::BindOnce(&NetworkConnectImpl::ConfigureSetProfileSucceeded,
+                     weak_factory_.GetWeakPtr(), network_id,
+                     base::Passed(&properties_to_set)),
+      base::BindOnce(&NetworkConnectImpl::SetPropertiesFailed,
+                     weak_factory_.GetWeakPtr(), "SetProfile: " + profile_path,
+                     network_id));
 }
 
 void NetworkConnectImpl::CreateConfigurationAndConnect(
diff --git a/chromeos/network/network_connection_handler_impl.cc b/chromeos/network/network_connection_handler_impl.cc
index 96eaf84f..a969449 100644
--- a/chromeos/network/network_connection_handler_impl.cc
+++ b/chromeos/network/network_connection_handler_impl.cc
@@ -619,10 +619,11 @@
     NET_LOG(EVENT) << "Configuring Network: " << NetworkPathId(service_path);
     configuration_handler_->SetShillProperties(
         service_path, config_properties,
-        base::Bind(&NetworkConnectionHandlerImpl::CallShillConnect, AsWeakPtr(),
-                   service_path),
-        base::Bind(&NetworkConnectionHandlerImpl::HandleConfigurationFailure,
-                   AsWeakPtr(), service_path));
+        base::BindOnce(&NetworkConnectionHandlerImpl::CallShillConnect,
+                       AsWeakPtr(), service_path),
+        base::BindOnce(
+            &NetworkConnectionHandlerImpl::HandleConfigurationFailure,
+            AsWeakPtr(), service_path));
     return;
   }
 
diff --git a/chromeos/network/network_connection_handler_impl_unittest.cc b/chromeos/network/network_connection_handler_impl_unittest.cc
index 2c61a16..797e8cf 100644
--- a/chromeos/network/network_connection_handler_impl_unittest.cc
+++ b/chromeos/network/network_connection_handler_impl_unittest.cc
@@ -205,8 +205,8 @@
         service_path,
         base::BindOnce(&NetworkConnectionHandlerImplTest::SuccessCallback,
                        base::Unretained(this)),
-        base::Bind(&NetworkConnectionHandlerImplTest::ErrorCallback,
-                   base::Unretained(this)),
+        base::BindOnce(&NetworkConnectionHandlerImplTest::ErrorCallback,
+                       base::Unretained(this)),
         true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
     task_environment_.RunUntilIdle();
   }
@@ -216,8 +216,8 @@
         service_path,
         base::BindOnce(&NetworkConnectionHandlerImplTest::SuccessCallback,
                        base::Unretained(this)),
-        base::Bind(&NetworkConnectionHandlerImplTest::ErrorCallback,
-                   base::Unretained(this)));
+        base::BindOnce(&NetworkConnectionHandlerImplTest::ErrorCallback,
+                       base::Unretained(this)));
     task_environment_.RunUntilIdle();
   }
 
diff --git a/chromeos/network/network_device_handler.h b/chromeos/network/network_device_handler.h
index 46bb883..807048c 100644
--- a/chromeos/network/network_device_handler.h
+++ b/chromeos/network/network_device_handler.h
@@ -68,7 +68,7 @@
       const std::string& device_path,
       const std::string& property_name,
       const base::Value& value,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   // Tells the device specified by |device_path| to register to the cellular
@@ -80,7 +80,7 @@
   virtual void RegisterCellularNetwork(
       const std::string& device_path,
       const std::string& network_id,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   // SIM PIN/PUK methods
@@ -103,7 +103,7 @@
   virtual void RequirePin(const std::string& device_path,
                           bool require_pin,
                           const std::string& pin,
-                          const base::Closure& callback,
+                          base::OnceClosure callback,
                           network_handler::ErrorCallback error_callback) = 0;
 
   // Sends the PIN code |pin| to the device |device_path|.
@@ -118,7 +118,7 @@
   // "not-supported" error if called on a non-cellular device.
   virtual void EnterPin(const std::string& device_path,
                         const std::string& pin,
-                        const base::Closure& callback,
+                        base::OnceClosure callback,
                         network_handler::ErrorCallback error_callback) = 0;
 
   // Sends the PUK code |puk| to the SIM to unblock a blocked SIM. On success,
@@ -134,7 +134,7 @@
   virtual void UnblockPin(const std::string& device_path,
                           const std::string& puk,
                           const std::string& new_pin,
-                          const base::Closure& callback,
+                          base::OnceClosure callback,
                           network_handler::ErrorCallback error_callback) = 0;
 
   // Tells the device to change the PIN code used to unlock a locked SIM card.
@@ -151,7 +151,7 @@
   virtual void ChangePin(const std::string& device_path,
                          const std::string& old_pin,
                          const std::string& new_pin,
-                         const base::Closure& callback,
+                         base::OnceClosure callback,
                          network_handler::ErrorCallback error_callback) = 0;
 
   // Enables/disables roaming of all cellular devices. This happens
@@ -171,34 +171,34 @@
   // should monitor to wake the system from suspend.
   virtual void AddWifiWakeOnPacketConnection(
       const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   // Adds |types| to the list of packet types that the device should monitor to
   // wake the system from suspend.
   virtual void AddWifiWakeOnPacketOfTypes(
       const std::vector<std::string>& types,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   // Removes |ip_endpoint| from the list of tcp connections that the wifi device
   // should monitor to wake the system from suspend.
   virtual void RemoveWifiWakeOnPacketConnection(
       const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   // Removes |types| from the list of packet types that the device should
   // monitor to wake the system from suspend.
   virtual void RemoveWifiWakeOnPacketOfTypes(
       const std::vector<std::string>& types,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   // Clears the list of tcp connections that the wifi device should monitor to
   // wake the system from suspend.
   virtual void RemoveAllWifiWakeOnPacketConnections(
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) = 0;
 
   static std::unique_ptr<NetworkDeviceHandler> InitializeForTesting(
diff --git a/chromeos/network/network_device_handler_impl.cc b/chromeos/network/network_device_handler_impl.cc
index d35ac34..5294bae 100644
--- a/chromeos/network/network_device_handler_impl.cc
+++ b/chromeos/network/network_device_handler_impl.cc
@@ -85,11 +85,11 @@
 void SetDevicePropertyInternal(const std::string& device_path,
                                const std::string& property_name,
                                const base::Value& value,
-                               const base::Closure& callback,
+                               base::OnceClosure callback,
                                network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "Device.SetProperty: " << property_name << " = " << value;
   ShillDeviceClient::Get()->SetProperty(
-      dbus::ObjectPath(device_path), property_name, value, callback,
+      dbus::ObjectPath(device_path), property_name, value, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_path,
                      std::move(error_callback)));
 }
@@ -121,7 +121,7 @@
     const std::string& device_path,
     const std::string& property_name,
     const base::Value& value,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const char* const property_blocked[] = {
       // Must only be changed by policy/owner through.
@@ -136,19 +136,19 @@
     }
   }
 
-  SetDevicePropertyInternal(device_path, property_name, value, callback,
-                            std::move(error_callback));
+  SetDevicePropertyInternal(device_path, property_name, value,
+                            std::move(callback), std::move(error_callback));
 }
 
 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
     const std::string& device_path,
     const std::string& network_id,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "Device.RegisterCellularNetwork: " << device_path
                 << " Id: " << network_id;
   ShillDeviceClient::Get()->Register(
-      dbus::ObjectPath(device_path), network_id, callback,
+      dbus::ObjectPath(device_path), network_id, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_path,
                      std::move(error_callback)));
 }
@@ -157,11 +157,11 @@
     const std::string& device_path,
     bool require_pin,
     const std::string& pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "Device.RequirePin: " << device_path << ": " << require_pin;
   ShillDeviceClient::Get()->RequirePin(
-      dbus::ObjectPath(device_path), pin, require_pin, callback,
+      dbus::ObjectPath(device_path), pin, require_pin, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_path,
                      std::move(error_callback)));
 }
@@ -169,11 +169,11 @@
 void NetworkDeviceHandlerImpl::EnterPin(
     const std::string& device_path,
     const std::string& pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "Device.EnterPin: " << device_path;
   ShillDeviceClient::Get()->EnterPin(
-      dbus::ObjectPath(device_path), pin, callback,
+      dbus::ObjectPath(device_path), pin, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_path,
                      std::move(error_callback)));
 }
@@ -182,11 +182,11 @@
     const std::string& device_path,
     const std::string& puk,
     const std::string& new_pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "Device.UnblockPin: " << device_path;
   ShillDeviceClient::Get()->UnblockPin(
-      dbus::ObjectPath(device_path), puk, new_pin, callback,
+      dbus::ObjectPath(device_path), puk, new_pin, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_path,
                      std::move(error_callback)));
 }
@@ -195,11 +195,11 @@
     const std::string& device_path,
     const std::string& old_pin,
     const std::string& new_pin,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   NET_LOG(USER) << "Device.ChangePin: " << device_path;
   ShillDeviceClient::Get()->ChangePin(
-      dbus::ObjectPath(device_path), old_pin, new_pin, callback,
+      dbus::ObjectPath(device_path), old_pin, new_pin, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_path,
                      std::move(error_callback)));
 }
@@ -229,7 +229,7 @@
 
 void NetworkDeviceHandlerImpl::AddWifiWakeOnPacketConnection(
     const net::IPEndPoint& ip_endpoint,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const DeviceState* device_state = GetWifiDeviceState();
   if (!device_state) {
@@ -242,14 +242,14 @@
 
   NET_LOG(USER) << "Device.AddWakeOnWifi: " << device_state->path();
   ShillDeviceClient::Get()->AddWakeOnPacketConnection(
-      dbus::ObjectPath(device_state->path()), ip_endpoint, callback,
+      dbus::ObjectPath(device_state->path()), ip_endpoint, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_state->path(),
                      std::move(error_callback)));
 }
 
 void NetworkDeviceHandlerImpl::AddWifiWakeOnPacketOfTypes(
     const std::vector<std::string>& types,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const DeviceState* device_state = GetWifiDeviceState();
   if (!device_state) {
@@ -263,14 +263,14 @@
   NET_LOG(USER) << "Device.AddWifiWakeOnPacketOfTypes: " << device_state->path()
                 << " Types: " << base::JoinString(types, " ");
   ShillDeviceClient::Get()->AddWakeOnPacketOfTypes(
-      dbus::ObjectPath(device_state->path()), types, callback,
+      dbus::ObjectPath(device_state->path()), types, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_state->path(),
                      std::move(error_callback)));
 }
 
 void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketConnection(
     const net::IPEndPoint& ip_endpoint,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const DeviceState* device_state = GetWifiDeviceState();
   if (!device_state) {
@@ -283,14 +283,14 @@
 
   NET_LOG(USER) << "Device.RemoveWakeOnWifi: " << device_state->path();
   ShillDeviceClient::Get()->RemoveWakeOnPacketConnection(
-      dbus::ObjectPath(device_state->path()), ip_endpoint, callback,
+      dbus::ObjectPath(device_state->path()), ip_endpoint, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_state->path(),
                      std::move(error_callback)));
 }
 
 void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketOfTypes(
     const std::vector<std::string>& types,
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const DeviceState* device_state = GetWifiDeviceState();
   if (!device_state) {
@@ -305,13 +305,13 @@
                 << device_state->path()
                 << " Types: " << base::JoinString(types, " ");
   ShillDeviceClient::Get()->RemoveWakeOnPacketOfTypes(
-      dbus::ObjectPath(device_state->path()), types, callback,
+      dbus::ObjectPath(device_state->path()), types, std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_state->path(),
                      std::move(error_callback)));
 }
 
 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
-    const base::Closure& callback,
+    base::OnceClosure callback,
     network_handler::ErrorCallback error_callback) {
   const DeviceState* device_state = GetWifiDeviceState();
   if (!device_state) {
@@ -324,7 +324,7 @@
 
   NET_LOG(USER) << "Device.RemoveAllWakeOnWifi: " << device_state->path();
   ShillDeviceClient::Get()->RemoveAllWakeOnPacketConnections(
-      dbus::ObjectPath(device_state->path()), callback,
+      dbus::ObjectPath(device_state->path()), std::move(callback),
       base::BindOnce(&HandleShillCallFailure, device_state->path(),
                      std::move(error_callback)));
 }
diff --git a/chromeos/network/network_device_handler_impl.h b/chromeos/network/network_device_handler_impl.h
index e6a128c..acae3b6 100644
--- a/chromeos/network/network_device_handler_impl.h
+++ b/chromeos/network/network_device_handler_impl.h
@@ -38,36 +38,36 @@
       const std::string& device_path,
       const std::string& property_name,
       const base::Value& value,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RegisterCellularNetwork(
       const std::string& device_path,
       const std::string& network_id,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RequirePin(const std::string& device_path,
                   bool require_pin,
                   const std::string& pin,
-                  const base::Closure& callback,
+                  base::OnceClosure callback,
                   network_handler::ErrorCallback error_callback) override;
 
   void EnterPin(const std::string& device_path,
                 const std::string& pin,
-                const base::Closure& callback,
+                base::OnceClosure callback,
                 network_handler::ErrorCallback error_callback) override;
 
   void UnblockPin(const std::string& device_path,
                   const std::string& puk,
                   const std::string& new_pin,
-                  const base::Closure& callback,
+                  base::OnceClosure callback,
                   network_handler::ErrorCallback error_callback) override;
 
   void ChangePin(const std::string& device_path,
                  const std::string& old_pin,
                  const std::string& new_pin,
-                 const base::Closure& callback,
+                 base::OnceClosure callback,
                  network_handler::ErrorCallback error_callback) override;
 
   void SetCellularAllowRoaming(bool allow_roaming) override;
@@ -78,26 +78,26 @@
 
   void AddWifiWakeOnPacketConnection(
       const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void AddWifiWakeOnPacketOfTypes(
       const std::vector<std::string>& types,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RemoveWifiWakeOnPacketConnection(
       const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RemoveWifiWakeOnPacketOfTypes(
       const std::vector<std::string>& types,
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   void RemoveAllWifiWakeOnPacketConnections(
-      const base::Closure& callback,
+      base::OnceClosure callback,
       network_handler::ErrorCallback error_callback) override;
 
   // NetworkStateHandlerObserver overrides
diff --git a/chromeos/network/network_device_handler_unittest.cc b/chromeos/network/network_device_handler_unittest.cc
index 0b6d750..e15cf850 100644
--- a/chromeos/network/network_device_handler_unittest.cc
+++ b/chromeos/network/network_device_handler_unittest.cc
@@ -74,9 +74,9 @@
     shill_clients::Shutdown();
   }
 
-  base::Closure GetSuccessCallback() {
-    return base::Bind(&NetworkDeviceHandlerTest::SuccessCallback,
-                      base::Unretained(this));
+  base::OnceClosure GetSuccessCallback() {
+    return base::BindOnce(&NetworkDeviceHandlerTest::SuccessCallback,
+                          base::Unretained(this));
   }
 
   network_handler::ErrorCallback GetErrorCallback() {
diff --git a/chromeos/network/network_ip_config.h b/chromeos/network/network_ip_config.h
index 0c8f94d..2e6914b 100644
--- a/chromeos/network/network_ip_config.h
+++ b/chromeos/network/network_ip_config.h
@@ -44,14 +44,6 @@
 
 typedef std::vector<NetworkIPConfig> NetworkIPConfigVector;
 
-// Used to return the list of IP configs and hardware address from an
-// asynchronous call to Shill. The hardware address is usually a MAC address
-// like "0011AA22BB33". |hardware_address| will be an empty string, if no
-// hardware address is found.
-typedef base::Callback<void(const NetworkIPConfigVector& ip_configs,
-                            const std::string& hardware_address)>
-    NetworkGetIPConfigsCallback;
-
 }  // namespace chromeos
 
 #endif  // CHROMEOS_NETWORK_NETWORK_IP_CONFIG_H_
diff --git a/chromeos/network/network_sms_handler.cc b/chromeos/network/network_sms_handler.cc
index c9d8c5b..e766184 100644
--- a/chromeos/network/network_sms_handler.cc
+++ b/chromeos/network/network_sms_handler.cc
@@ -88,9 +88,10 @@
   // Set the handler for received Sms messaages.
   ModemMessagingClient::Get()->SetSmsReceivedHandler(
       service_name_, object_path_,
-      base::Bind(&NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::
-                     SmsReceivedCallback,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(
+          &NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::
+              SmsReceivedCallback,
+          weak_ptr_factory_.GetWeakPtr()));
 
   // List the existing messages.
   ModemMessagingClient::Get()->List(
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index ee51632f..8359b92 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -1247,7 +1247,7 @@
               NetworkTypePattern::Ethernet());
       if (ethernet) {
         config_handler->SetShillProperties(ethernet->path(), *shill_dict,
-                                           base::Closure(),
+                                           base::OnceClosure(),
                                            network_handler::ErrorCallback());
       } else {
         ethernet_not_found = true;
diff --git a/chromeos/network/proxy/proxy_config_service_impl.cc b/chromeos/network/proxy/proxy_config_service_impl.cc
index 0ac353e..dcd0d37 100644
--- a/chromeos/network/proxy/proxy_config_service_impl.cc
+++ b/chromeos/network/proxy/proxy_config_service_impl.cc
@@ -59,7 +59,7 @@
           io_task_runner),
       profile_prefs_(profile_prefs),
       local_state_prefs_(local_state_prefs) {
-  const base::Closure proxy_change_callback = base::Bind(
+  const base::RepeatingClosure proxy_change_callback = base::BindRepeating(
       &ProxyConfigServiceImpl::OnProxyPrefChanged, base::Unretained(this));
 
   if (profile_prefs) {
diff --git a/chromeos/network/proxy/ui_proxy_config_service.cc b/chromeos/network/proxy/ui_proxy_config_service.cc
index 6cb6145..1256b05f 100644
--- a/chromeos/network/proxy/ui_proxy_config_service.cc
+++ b/chromeos/network/proxy/ui_proxy_config_service.cc
@@ -191,20 +191,20 @@
     profile_registrar_.Init(profile_prefs_);
     profile_registrar_.Add(
         ::proxy_config::prefs::kProxy,
-        base::Bind(&UIProxyConfigService::OnPreferenceChanged,
-                   base::Unretained(this)));
+        base::BindRepeating(&UIProxyConfigService::OnPreferenceChanged,
+                            base::Unretained(this)));
     profile_registrar_.Add(
         ::proxy_config::prefs::kUseSharedProxies,
-        base::Bind(&UIProxyConfigService::OnPreferenceChanged,
-                   base::Unretained(this)));
+        base::BindRepeating(&UIProxyConfigService::OnPreferenceChanged,
+                            base::Unretained(this)));
   }
 
   DCHECK(local_state_prefs_);
   local_state_registrar_.Init(local_state_prefs_);
   local_state_registrar_.Add(
       ::proxy_config::prefs::kProxy,
-      base::Bind(&UIProxyConfigService::OnPreferenceChanged,
-                 base::Unretained(this)));
+      base::BindRepeating(&UIProxyConfigService::OnPreferenceChanged,
+                          base::Unretained(this)));
   network_state_handler_ = network_state_handler;
   network_profile_handler_ = network_profile_handler;
 }
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc
index 61f8687..d226ef5 100644
--- a/chromeos/network/shill_property_handler.cc
+++ b/chromeos/network/shill_property_handler.cc
@@ -52,11 +52,10 @@
 // OnPropertyChanged is called.
 class ShillPropertyObserver : public ShillPropertyChangedObserver {
  public:
-  typedef base::Callback<void(ManagedState::ManagedType type,
-                              const std::string& service,
-                              const std::string& name,
-                              const base::Value& value)>
-      Handler;
+  using Handler = base::RepeatingCallback<void(ManagedState::ManagedType type,
+                                               const std::string& service,
+                                               const std::string& name,
+                                               const base::Value& value)>;
 
   ShillPropertyObserver(ManagedState::ManagedType type,
                         const std::string& path,
@@ -434,8 +433,8 @@
       // Create an observer for future updates.
       observer = std::make_unique<ShillPropertyObserver>(
           type, path,
-          base::Bind(&ShillPropertyHandler::PropertyChangedCallback,
-                     AsWeakPtr()));
+          base::BindRepeating(&ShillPropertyHandler::PropertyChangedCallback,
+                              AsWeakPtr()));
     }
     auto result =
         new_observed.insert(std::make_pair(path, std::move(observer)));
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom b/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
index ab21774..294b022 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
+++ b/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
@@ -24,7 +24,6 @@
 enum ProbeCategoryEnum {
   kBattery,
   kNonRemovableBlockDevices,
-  kCachedVpdData,
   kCpu,
   kTimezone,
   kMemory,
@@ -32,6 +31,7 @@
   kFan,
   kStatefulPartition,
   kBluetooth,
+  kSystem,
 };
 
 // An enumeration of the different categories of errors that can occur when
@@ -149,21 +149,6 @@
   UInt64Value? discard_time_seconds_since_last_boot;
 };
 
-// Cached VPD probe result. Can either be populated with the CachedVpdInfo or an
-// error retrieving the information.
-union CachedVpdResult {
-  // Valid CachedVpdInfo.
-  CachedVpdInfo vpd_info;
-  // The error that occurred attempting to retrieve the CachedVpdInfo.
-  ProbeError error;
-};
-
-// Cached VPD read from sysfs.
-struct CachedVpdInfo {
-  // Contents of /sys/firmware/vpd/ro/sku_number, if the device supports it.
-  string? sku_number;
-};
-
 // CPU probe result. Can either be populated with the CpuInfo or an error
 // retrieving the information.
 union CpuResult {
@@ -326,6 +311,41 @@
   uint32 num_connected_devices;
 };
 
+// System probe result. Can either be populated with the SystemInfo or an error
+// retrieving the information.
+union SystemResult {
+  // Valid SystemInfo.
+  SystemInfo system_info;
+  // The error that occurred attempting to retrieve SystemInfo.
+  ProbeError error;
+};
+
+// System Information.
+struct SystemInfo {
+  // The date the device was first activated.
+  // Format: YYYY-WW.
+  string? first_power_date;
+  // The date the device was manufactured (finalized in factory).
+  // Format: YYYY-MM-DD.
+  string? manufacture_date;
+  // The product SKU number.
+  string? product_sku_number;
+  // Contents of CrosConfig in /arc/build-properties/marketing-name.
+  string marketing_name;
+  // The BIOS version.
+  string? bios_version;
+  // The product name of the motherboard.
+  string? board_name;
+  // The version of the motherboard.
+  string? board_version;
+  // The chassis type of the device. The values reported by chassis type are
+  // mapped in
+  // www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf.
+  UInt64Value? chassis_type;
+  // The product name (model) of the system.
+  string? product_name;
+};
+
 // A collection of all the device's telemetry information that cros_healthd is
 // capable of reporting. Note that every field in TelemetryInfo is nullable, and
 // the response for a particular ProbeTelemetryInfo request will only contain
@@ -341,9 +361,6 @@
   // present when kNonRemovableBlockDevices was included in the categories input
   // to ProbeTelemetryInfo.
   NonRemovableBlockDeviceResult? block_device_result;
-  // Only present when kCachedVpdData was included in the categories input to
-  // ProbeTelemetryInfo.
-  CachedVpdResult? vpd_result;
   // Information about each of the device's CPUs. Only present when kCpu was
   // included in the categories input to ProbeTelemetryInfo.
   CpuResult? cpu_result;
@@ -366,4 +383,7 @@
   // Information about the device's Bluetooth adapters and devices. Only present
   // when kBluetooth was included in the categories input to ProbeTelemetryInfo.
   BluetoothResult? bluetooth_result;
+  // Information about the system from various sources. Only present when
+  // kSystem was included in the categories input to ProbeTelemetryInfo.
+  SystemResult? system_result;
 };
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc
index e2e5186..0eee677 100644
--- a/chromeos/settings/cros_settings_names.cc
+++ b/chromeos/settings/cros_settings_names.cc
@@ -198,6 +198,11 @@
 // included in status reports to the device management server.
 const char kReportDeviceVpdInfo[] = "cros.device_status.report_device_vpd_info";
 
+// A boolean pref that determines whether the device's system information should
+// be included in status reports to the device management server.
+const char kReportDeviceSystemInfo[] =
+    "cros.device_status.report_device_system_info";
+
 // Determines whether heartbeats should be sent to the policy service via
 // the GCM channel.
 const char kHeartbeatEnabled[] = "cros.device_status.heartbeat_enabled";
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h
index 9dc3292..4d35227f 100644
--- a/chromeos/settings/cros_settings_names.h
+++ b/chromeos/settings/cros_settings_names.h
@@ -115,6 +115,7 @@
 extern const char kReportDeviceBluetoothInfo[];
 COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceFanInfo[];
 COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceVpdInfo[];
+COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceSystemInfo[];
 
 COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kHeartbeatEnabled[];
 COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kHeartbeatFrequency[];
diff --git a/components/BUILD.gn b/components/BUILD.gn
index f3e9fd4..e3d8755 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -336,7 +336,6 @@
       "//components/invalidation/impl",
       "//components/offline_items_collection/core:native_java_unittests_java",
       "//components/paint_preview/browser/android:java",
-      "//components/paint_preview/browser/android:unit_tests",
       "//components/paint_preview/player/android:unit_tests",
       "//components/permissions/android:java",
       "//components/policy/android:policy_java",
diff --git a/components/cronet/tools/generate_javadoc.py b/components/cronet/tools/generate_javadoc.py
index eb3c4c45..cc878ca 100755
--- a/components/cronet/tools/generate_javadoc.py
+++ b/components/cronet/tools/generate_javadoc.py
@@ -26,6 +26,14 @@
 SDK_DIR = os.path.join(REPOSITORY_ROOT, 'third_party', 'android_sdk', 'public')
 JAVADOC_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'javadoc')
 
+JAVADOC_WARNING = """\
+javadoc: warning - The old Doclet and Taglet APIs in the packages
+com.sun.javadoc, com.sun.tools.doclets and their implementations
+are planned to be removed in a future JDK release. These
+components have been superseded by the new APIs in jdk.javadoc.doclet.
+Users are strongly recommended to migrate to the new APIs.
+"""
+
 class CronetPostprocessor(Postprocessor):
   def run(self, text):
     return text.replace('@Override', '&commat;Override')
@@ -69,7 +77,11 @@
       if filename.endswith(".java"):
         javadoc_cmd += [os.path.join(subdir, filename)]
   try:
-    build_utils.CheckOutput(javadoc_cmd, cwd=working_dir)
+    def stderr_filter(stderr):
+      return stderr.replace(JAVADOC_WARNING, '')
+
+    build_utils.CheckOutput(javadoc_cmd, cwd=working_dir,
+                            stderr_filter=stderr_filter)
   except build_utils.CalledProcessError:
     build_utils.DeleteDirectory(output_dir)
     raise
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index acc02bc..d84ee94 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -651,6 +651,7 @@
 void DownloadItemImpl::Cancel(bool user_cancel) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DVLOG(20) << __func__ << "() download = " << DebugString(true);
+  download_schedule_ = base::nullopt;
   InterruptAndDiscardPartialState(
       user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
                   : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
@@ -1845,6 +1846,8 @@
     return;
   }
 
+  download_schedule_ = base::nullopt;
+
   TransitionTo(IN_PROGRESS_INTERNAL);
   // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is
   // not safe. The download could be in an underminate state after invoking
diff --git a/components/download/internal/common/download_item_impl_unittest.cc b/components/download/internal/common/download_item_impl_unittest.cc
index 2039953..39d60b8 100644
--- a/components/download/internal/common/download_item_impl_unittest.cc
+++ b/components/download/internal/common/download_item_impl_unittest.cc
@@ -2699,6 +2699,11 @@
     ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_CRASH, item->GetLastReason());
   }
 
+  if (param.state == DownloadItem::IN_PROGRESS) {
+    EXPECT_FALSE(item->GetDownloadSchedule().has_value())
+        << "Download schedule should be cleared before completion.";
+  }
+
   CleanupItem(item, download_file, param.state);
 }
 
@@ -2736,5 +2741,21 @@
   }
 }
 
+TEST_F(DownloadItemTest, CancelWithDownloadSchedule) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kDownloadLater);
+
+  auto item = CreateDownloadItem(DownloadItem::DownloadState::INTERRUPTED,
+                                 DOWNLOAD_INTERRUPT_REASON_CRASH);
+  auto download_schedule = base::make_optional<DownloadSchedule>(
+      false, base::Time::Now() + base::TimeDelta::FromDays(10));
+  item->OnDownloadScheduleChanged(std::move(download_schedule));
+
+  EXPECT_EQ(item->GetState(), DownloadItem::DownloadState::INTERRUPTED);
+  EXPECT_TRUE(item->GetDownloadSchedule().has_value());
+  item->Cancel(true);
+  EXPECT_FALSE(item->GetDownloadSchedule().has_value());
+}
+
 }  // namespace
 }  // namespace download
diff --git a/components/history/core/browser/top_sites_impl.cc b/components/history/core/browser/top_sites_impl.cc
index 415f43e..f48ddae 100644
--- a/components/history/core/browser/top_sites_impl.cc
+++ b/components/history/core/browser/top_sites_impl.cc
@@ -300,13 +300,6 @@
 
 MostVisitedURLList TopSitesImpl::ApplyBlockedUrls(
     const MostVisitedURLList& urls) {
-  // Log the number of times ApplyBlockedUrls is called so we can compute the
-  // average number of blocked urls per user.
-  const base::DictionaryValue* blocked_urls =
-      pref_service_->GetDictionary(kBlockedUrlsPrefsKey);
-  UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true);
-  UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems",
-                           (blocked_urls ? blocked_urls->size() : 0));
   MostVisitedURLList result;
   for (const auto& url : urls) {
     if (IsBlocked(url.url))
diff --git a/components/lookalikes/core/lookalike_url_ui_util.cc b/components/lookalikes/core/lookalike_url_ui_util.cc
index dde4f90..b15d543 100644
--- a/components/lookalikes/core/lookalike_url_ui_util.cc
+++ b/components/lookalikes/core/lookalike_url_ui_util.cc
@@ -70,10 +70,12 @@
     // domain fails IDN spoof checks but isn't a lookalike of a known domain.
     // TODO: Change to actual strings.
     load_time_data->SetString(
-        "heading", l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_TITLE));
+        "heading",
+        l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_HEADING_NO_SUGGESTED_URL));
     load_time_data->SetString(
         "primaryParagraph",
-        l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH));
+        l10n_util::GetStringUTF16(
+            IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH_NO_SUGGESTED_URL));
     load_time_data->SetString(
         "proceedButtonText",
         l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_IGNORE));
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc
index 0d3c203..6062b82 100644
--- a/components/omnibox/browser/clipboard_provider.cc
+++ b/components/omnibox/browser/clipboard_provider.cc
@@ -33,6 +33,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/url_formatter.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_util.h"
 
 namespace {
@@ -376,18 +377,20 @@
   if (!optional_image)
     return;
   done_ = false;
+  gfx::ImageSkia image_skia = *optional_image.value().ToImageSkia();
+  image_skia.MakeThreadSafe();
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&ClipboardProvider::EncodeClipboardImage,
-                     optional_image.value()),
+      base::BindOnce(&ClipboardProvider::EncodeClipboardImage, image_skia),
       base::BindOnce(&ClipboardProvider::ConstructImageMatchCallback,
                      callback_weak_ptr_factory_.GetWeakPtr(), input,
                      url_service, clipboard_contents_age));
 }
 
 scoped_refptr<base::RefCountedMemory> ClipboardProvider::EncodeClipboardImage(
-    gfx::Image image) {
-  gfx::Image resized_image = gfx::ResizedImageForSearchByImage(image);
+    gfx::ImageSkia image_skia) {
+  gfx::Image resized_image =
+      gfx::ResizedImageForSearchByImage(gfx::Image(image_skia));
   return resized_image.As1xPNGBytes();
 }
 
diff --git a/components/omnibox/browser/clipboard_provider.h b/components/omnibox/browser/clipboard_provider.h
index d084ff6..86456094 100644
--- a/components/omnibox/browser/clipboard_provider.h
+++ b/components/omnibox/browser/clipboard_provider.h
@@ -63,7 +63,7 @@
   // Resize and encode the image data into bytes. This can take some time if the
   // image is large, so this should happen on a background thread.
   static scoped_refptr<base::RefCountedMemory> EncodeClipboardImage(
-      gfx::Image image);
+      gfx::ImageSkia image);
   // Construct the actual image match once the image has been encoded into
   // bytes. This should be called back on the main thread.
   void ConstructImageMatchCallback(
diff --git a/components/omnibox/browser/clipboard_provider_unittest.cc b/components/omnibox/browser/clipboard_provider_unittest.cc
index db38514..e230484 100644
--- a/components/omnibox/browser/clipboard_provider_unittest.cc
+++ b/components/omnibox/browser/clipboard_provider_unittest.cc
@@ -25,6 +25,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_unittest_util.h"
 #include "url/gurl.h"
 
@@ -156,7 +157,7 @@
 
   gfx::Image test_image = gfx::test::CreateImage(/*height=*/10, /*width=*/10);
   scoped_refptr<base::RefCountedMemory> image_bytes =
-      provider_->EncodeClipboardImage(test_image);
+      provider_->EncodeClipboardImage(*test_image.ToImageSkia());
   ASSERT_TRUE(image_bytes);
   provider_->ConstructImageMatchCallback(CreateAutocompleteInput(true),
                                          &template_url_service, clipboard_age,
diff --git a/components/paint_preview/browser/android/BUILD.gn b/components/paint_preview/browser/android/BUILD.gn
index 5885b04..6184c9d3e 100644
--- a/components/paint_preview/browser/android/BUILD.gn
+++ b/components/paint_preview/browser/android/BUILD.gn
@@ -6,62 +6,6 @@
 
 assert(is_android, "This directory should only be compiled for Android.")
 
-generate_jni("jni_headers") {
-  sources = [ "java/src/org/chromium/components/paintpreview/browser/PaintPreviewUtils.java" ]
-}
-
 android_library("java") {
-  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
-
-  sources = [
-    "java/src/org/chromium/components/paintpreview/browser/NativePaintPreviewServiceProvider.java",
-    "java/src/org/chromium/components/paintpreview/browser/PaintPreviewUtils.java",
-  ]
-
-  deps = [
-    "//base:base_java",
-    "//base:jni_java",
-    "//content/public/android:content_java",
-  ]
-}
-
-source_set("android") {
-  sources = [
-    "paint_preview_utils.cc",
-    "paint_preview_utils.h",
-  ]
-
-  deps = [
-    ":jni_headers",
-    "//base",
-    "//components/paint_preview/browser",
-    "//components/paint_preview/buildflags",
-    "//components/ukm/content",
-    "//content/public/browser",
-    "//services/metrics/public/cpp:ukm_builders",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-
-  sources = [ "paint_preview_utils_unittest.cc" ]
-
-  deps = [
-    ":android",
-    "//base",
-    "//base/test:test_support",
-    "//components/paint_preview/common:test_utils",
-    "//components/paint_preview/common/mojom",
-    "//components/ukm:test_support",
-    "//components/ukm/content",
-    "//content/public/browser",
-    "//content/test:test_support",
-    "//services/metrics/public/cpp:ukm_builders",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//third_party/blink/public:blink_headers",
-    "//third_party/blink/public/common",
-    "//third_party/zlib/google:zip",
-  ]
+  sources = [ "java/src/org/chromium/components/paintpreview/browser/NativePaintPreviewServiceProvider.java" ]
 }
diff --git a/components/paint_preview/browser/android/java/DEPS b/components/paint_preview/browser/android/java/DEPS
deleted file mode 100644
index 5beb9bb..0000000
--- a/components/paint_preview/browser/android/java/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+content/public/android/java/src/org/chromium/content_public/browser/WebContents.java",
-]
diff --git a/components/paint_preview/browser/android/java/src/org/chromium/components/paintpreview/browser/PaintPreviewUtils.java b/components/paint_preview/browser/android/java/src/org/chromium/components/paintpreview/browser/PaintPreviewUtils.java
deleted file mode 100644
index 5e4fcdcc..0000000
--- a/components/paint_preview/browser/android/java/src/org/chromium/components/paintpreview/browser/PaintPreviewUtils.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.paintpreview.browser;
-
-import org.chromium.base.annotations.NativeMethods;
-import org.chromium.content_public.browser.WebContents;
-
-/**
- * Helper to capture paint previews via native.
- */
-public class PaintPreviewUtils {
-    /**
-     * Captures a paint preview of the passed contents.
-     * @param contents The WebContents of the page to capture.
-     */
-    public static void capturePaintPreview(WebContents contents) {
-        PaintPreviewUtilsJni.get().capturePaintPreview(contents);
-    }
-
-    @NativeMethods
-    interface Natives {
-        void capturePaintPreview(WebContents webContents);
-    }
-}
diff --git a/components/paint_preview/browser/android/paint_preview_utils.cc b/components/paint_preview/browser/android/paint_preview_utils.cc
deleted file mode 100644
index 8b8ad53a..0000000
--- a/components/paint_preview/browser/android/paint_preview_utils.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/paint_preview/browser/android/paint_preview_utils.h"
-
-#include <jni.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/task/post_task.h"
-#include "base/task/thread_pool.h"
-#include "base/unguessable_token.h"
-#include "components/paint_preview/browser/android/jni_headers/PaintPreviewUtils_jni.h"
-#include "components/paint_preview/browser/file_manager.h"
-#include "components/paint_preview/browser/paint_preview_client.h"
-#include "components/paint_preview/buildflags/buildflags.h"
-#include "components/ukm/content/source_url_recorder.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-#include "services/metrics/public/cpp/metrics_utils.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
-
-namespace paint_preview {
-
-namespace {
-
-const char kPaintPreviewTestTag[] = "PaintPreviewTest ";
-const char kPaintPreviewDir[] = "paint_preview";
-const char kCaptureTestDir[] = "capture_test";
-
-struct CaptureMetrics {
-  base::TimeDelta capture_time;
-  ukm::SourceId source_id;
-};
-
-void CleanupOnFailure(const base::FilePath& root_dir,
-                      FinishedCallback finished) {
-  VLOG(1) << kPaintPreviewTestTag << "Capture Failed\n";
-  base::DeletePathRecursively(root_dir);
-  std::move(finished).Run(base::nullopt);
-}
-
-void CleanupAndLogResult(const base::FilePath& zip_path,
-                         const CaptureMetrics& metrics,
-                         FinishedCallback finished,
-                         bool keep_zip,
-                         size_t compressed_size_bytes) {
-  VLOG(1) << kPaintPreviewTestTag << "Capture Finished Successfully:\n"
-          << "Compressed size " << compressed_size_bytes << " bytes\n"
-          << "Time taken in native " << metrics.capture_time.InMilliseconds()
-          << " ms";
-
-  if (!keep_zip)
-    base::DeletePathRecursively(zip_path.DirName());
-
-  base::UmaHistogramMemoryKB(
-      "Browser.PaintPreview.CaptureExperiment.CompressedOnDiskSize",
-      compressed_size_bytes / 1000);
-  if (metrics.source_id != ukm::kInvalidSourceId) {
-    ukm::builders::PaintPreviewCapture(metrics.source_id)
-        .SetCompressedOnDiskSize(
-            ukm::GetExponentialBucketMinForBytes(compressed_size_bytes))
-        .Record(ukm::UkmRecorder::Get());
-  }
-  std::move(finished).Run(zip_path);
-}
-
-void MeasureSize(scoped_refptr<FileManager> manager,
-                 const DirectoryKey& key,
-                 const base::FilePath& root_dir,
-                 CaptureMetrics metrics,
-                 FinishedCallback finished,
-                 bool keep_zip,
-                 bool success) {
-  if (!success) {
-    CleanupOnFailure(root_dir, std::move(finished));
-    return;
-  }
-  manager->GetTaskRunner()->PostTaskAndReplyWithResult(
-      FROM_HERE, base::BindOnce(&FileManager::GetSizeOfArtifacts, manager, key),
-      base::BindOnce(
-          &CleanupAndLogResult,
-          root_dir.AppendASCII(key.AsciiDirname()).AddExtensionASCII("zip"),
-          metrics, std::move(finished), keep_zip));
-}
-
-void OnCaptured(scoped_refptr<FileManager> manager,
-                const DirectoryKey& key,
-                base::TimeTicks start_time,
-                const base::FilePath& root_dir,
-                ukm::SourceId source_id,
-                FinishedCallback finished,
-                bool keep_zip,
-                base::UnguessableToken guid,
-                mojom::PaintPreviewStatus status,
-                std::unique_ptr<PaintPreviewProto> proto) {
-  base::TimeDelta time_delta = base::TimeTicks::Now() - start_time;
-
-  bool success = (status == mojom::PaintPreviewStatus::kOk);
-  base::UmaHistogramBoolean("Browser.PaintPreview.CaptureExperiment.Success",
-                            success);
-  if (!success || !proto) {
-    base::ThreadPool::PostTask(
-        FROM_HERE, {base::MayBlock()},
-        base::BindOnce(&CleanupOnFailure, root_dir, std::move(finished)));
-    return;
-  }
-
-  CaptureMetrics result = {time_delta, source_id};
-  manager->GetTaskRunner()->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&FileManager::SerializePaintPreviewProto, manager, key,
-                     *proto, true),
-      base::BindOnce(&MeasureSize, manager, key, root_dir, result,
-                     std::move(finished), keep_zip));
-}
-
-void InitiateCapture(scoped_refptr<FileManager> manager,
-                     const DirectoryKey& key,
-                     int frame_tree_node_id,
-                     FinishedCallback finished,
-                     bool keep_zip,
-                     const base::Optional<base::FilePath>& url_path) {
-  auto* contents =
-      content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
-  if (!url_path.has_value() || !contents) {
-    std::move(finished).Run(base::nullopt);
-    return;
-  }
-
-  auto* client = PaintPreviewClient::FromWebContents(contents);
-  if (!client) {
-    VLOG(1) << kPaintPreviewTestTag << "Failure: client could not be created.";
-    CleanupOnFailure(url_path->DirName(), std::move(finished));
-    return;
-  }
-
-  PaintPreviewClient::PaintPreviewParams params;
-  params.document_guid = base::UnguessableToken::Create();
-  params.is_main_frame = true;
-  params.root_dir = url_path.value();
-  params.max_per_capture_size = 0;  // Unlimited size.
-
-  ukm::SourceId source_id = ukm::GetSourceIdForWebContentsDocument(contents);
-  auto start_time = base::TimeTicks::Now();
-  client->CapturePaintPreview(
-      params, contents->GetMainFrame(),
-      base::BindOnce(&OnCaptured, manager, key, start_time,
-                     params.root_dir.DirName(), source_id, std::move(finished),
-                     keep_zip));
-}
-
-}  // namespace
-
-void Capture(content::WebContents* contents,
-             FinishedCallback finished,
-             bool keep_zip) {
-  PaintPreviewClient::CreateForWebContents(contents);
-  base::FilePath root_path = contents->GetBrowserContext()
-                                 ->GetPath()
-                                 .AppendASCII(kPaintPreviewDir)
-                                 .AppendASCII(kCaptureTestDir);
-  auto manager = base::MakeRefCounted<FileManager>(
-      root_path, base::ThreadPool::CreateSequencedTaskRunner(
-                     {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
-                      base::TaskShutdownBehavior::BLOCK_SHUTDOWN,
-                      base::ThreadPolicy::MUST_USE_FOREGROUND}));
-
-  auto key = manager->CreateKey(contents->GetLastCommittedURL());
-  manager->GetTaskRunner()->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&FileManager::CreateOrGetDirectory, manager, key, true),
-      base::BindOnce(&InitiateCapture, manager, key,
-                     contents->GetMainFrame()->GetFrameTreeNodeId(),
-                     std::move(finished), keep_zip));
-}
-
-}  // namespace paint_preview
-
-// If the ENABLE_PAINT_PREVIEW buildflags is set this method will trigger a
-// series of actions;
-// 1. Capture a paint preview via the client and measure the time taken.
-// 2. Zip a folder containing the artifacts and measure the size of the zip.
-// 3. Delete the resulting zip archive.
-// 4. Log the results.
-// If the buildflag is not set this is just a stub.
-static void JNI_PaintPreviewUtils_CapturePaintPreview(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& jweb_contents) {
-#if BUILDFLAG(ENABLE_PAINT_PREVIEW)
-  auto* contents = content::WebContents::FromJavaWebContents(jweb_contents);
-  paint_preview::Capture(contents, base::DoNothing(), /* keep_zip= */ false);
-#else
-  // In theory this is unreachable as the codepath to reach here is only exposed
-  // if the buildflag for ENABLE_PAINT_PREVIEW is set. However, this function
-  // will still be compiled as it is called from JNI so this is here as a
-  // placeholder.
-  VLOG(1) << paint_preview::kPaintPreviewTestTag
-          << "Failure: compiled without buildflag ENABLE_PAINT_PREVIEW.";
-#endif  // BUILDFLAG(ENABLE_PAINT_PREVIEW)
-}
diff --git a/components/paint_preview/browser/android/paint_preview_utils.h b/components/paint_preview/browser/android/paint_preview_utils.h
deleted file mode 100644
index d517680..0000000
--- a/components/paint_preview/browser/android/paint_preview_utils.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PAINT_PREVIEW_BROWSER_ANDROID_PAINT_PREVIEW_UTILS_H_
-#define COMPONENTS_PAINT_PREVIEW_BROWSER_ANDROID_PAINT_PREVIEW_UTILS_H_
-
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
-#include "base/optional.h"
-
-namespace content {
-class WebContents;
-}  // namespace content
-
-namespace paint_preview {
-
-using FinishedCallback =
-    base::OnceCallback<void(const base::Optional<base::FilePath>&)>;
-
-// Captures a paint preview of |contents|. On completion returns the path of the
-// zip archive in which the paint preview is stored via |finished| (or an empty
-// path if the capture failed). The zip archive will exist only if |keep_zip| is
-// true.
-void Capture(content::WebContents* contents,
-             FinishedCallback finished,
-             bool keep_zip);
-
-}  // namespace paint_preview
-
-#endif  // COMPONENTS_PAINT_PREVIEW_BROWSER_ANDROID_PAINT_PREVIEW_UTILS_H_
diff --git a/components/paint_preview/browser/android/paint_preview_utils_unittest.cc b/components/paint_preview/browser/android/paint_preview_utils_unittest.cc
deleted file mode 100644
index c1df397f..0000000
--- a/components/paint_preview/browser/android/paint_preview_utils_unittest.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/paint_preview/browser/android/paint_preview_utils.h"
-
-#include <utility>
-
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
-#include "components/ukm/content/source_url_recorder.h"
-#include "components/ukm/test_ukm_recorder.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/test_renderer_host.h"
-#include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "services/metrics/public/cpp/ukm_source.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "third_party/zlib/google/zip.h"
-
-namespace paint_preview {
-
-namespace {
-
-class MockPaintPreviewRecorder : public mojom::PaintPreviewRecorder {
- public:
-  MockPaintPreviewRecorder() = default;
-  ~MockPaintPreviewRecorder() override = default;
-
-  MockPaintPreviewRecorder(const MockPaintPreviewRecorder&) = delete;
-  MockPaintPreviewRecorder& operator=(const MockPaintPreviewRecorder&) = delete;
-
-  void CapturePaintPreview(
-      mojom::PaintPreviewCaptureParamsPtr params,
-      mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback)
-      override {
-    std::move(callback).Run(status_, mojom::PaintPreviewCaptureResponse::New());
-  }
-
-  void SetResponseStatus(mojom::PaintPreviewStatus status) { status_ = status; }
-
-  void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) {
-    binding_.Bind(mojo::PendingAssociatedReceiver<mojom::PaintPreviewRecorder>(
-        std::move(handle)));
-  }
-
- private:
-  mojom::PaintPreviewStatus status_;
-  mojo::AssociatedReceiver<mojom::PaintPreviewRecorder> binding_{this};
-};
-
-base::Optional<base::FilePath> Unzip(const base::FilePath& zip) {
-  base::FilePath dst_path = zip.RemoveExtension();
-  if (!base::CreateDirectory(dst_path))
-    return base::nullopt;
-  if (!zip::Unzip(zip, dst_path))
-    return base::nullopt;
-  base::DeletePathRecursively(zip);
-  return dst_path;
-}
-
-}  // namespace
-
-class PaintPreviewUtilsRenderViewHostTest
-    : public content::RenderViewHostTestHarness {
- public:
-  PaintPreviewUtilsRenderViewHostTest() {}
-
-  PaintPreviewUtilsRenderViewHostTest(
-      const PaintPreviewUtilsRenderViewHostTest&) = delete;
-  PaintPreviewUtilsRenderViewHostTest& operator=(
-      const PaintPreviewUtilsRenderViewHostTest&) = delete;
-
- protected:
-  void SetUp() override {
-    RenderViewHostTestHarness::SetUp();
-    content::RenderFrameHostTester::For(main_rfh())
-        ->InitializeRenderFrameIfNeeded();
-    ukm::InitializeSourceUrlRecorderForWebContents(web_contents());
-  }
-
-  void OverrideInterface(MockPaintPreviewRecorder* service) {
-    blink::AssociatedInterfaceProvider* remote_interfaces =
-        web_contents()->GetMainFrame()->GetRemoteAssociatedInterfaces();
-    remote_interfaces->OverrideBinderForTesting(
-        mojom::PaintPreviewRecorder::Name_,
-        base::BindRepeating(&MockPaintPreviewRecorder::BindRequest,
-                            base::Unretained(service)));
-  }
-};
-
-TEST_F(PaintPreviewUtilsRenderViewHostTest, CaptureSingleFrameAndKeep) {
-  content::NavigationSimulator::NavigateAndCommitFromBrowser(
-      web_contents(), GURL("http://www.example.com"));
-  auto* contents = content::WebContents::FromRenderFrameHost(main_rfh());
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  MockPaintPreviewRecorder service;
-  service.SetResponseStatus(mojom::PaintPreviewStatus::kOk);
-  OverrideInterface(&service);
-
-  base::RunLoop loop;
-  Capture(contents,
-          base::BindOnce(
-              [](base::OnceClosure quit,
-                 const base::Optional<base::FilePath>& maybe_zip_path) {
-                EXPECT_TRUE(maybe_zip_path.has_value());
-
-                const base::FilePath& zip_path = maybe_zip_path.value();
-                EXPECT_EQ(".zip", zip_path.Extension());
-                {
-                  base::ScopedAllowBlockingForTesting scope;
-                  EXPECT_TRUE(base::PathExists(zip_path));
-                  auto unzipped_path = Unzip(zip_path);
-                  EXPECT_TRUE(unzipped_path.has_value());
-
-                  base::FileEnumerator enumerate(unzipped_path.value(), false,
-                                                 base::FileEnumerator::FILES);
-                  size_t count = 0;
-                  bool has_proto = false;
-                  bool has_skp = false;
-                  for (base::FilePath name = enumerate.Next(); !name.empty();
-                       name = enumerate.Next(), ++count) {
-                    if (name.Extension() == ".skp")
-                      has_skp = true;
-                    if (name.BaseName().AsUTF8Unsafe() == "proto.pb")
-                      has_proto = true;
-                  }
-                  EXPECT_EQ(2U, count);
-                  EXPECT_TRUE(has_skp);
-                  EXPECT_TRUE(has_proto);
-                  base::DeletePathRecursively(zip_path.DirName());
-                }
-                std::move(quit).Run();
-              },
-              loop.QuitClosure()),
-          true);
-  loop.Run();
-
-  auto entries = ukm_recorder.GetEntriesByName(
-      ukm::builders::PaintPreviewCapture::kEntryName);
-  EXPECT_EQ(2U, entries.size());
-}
-
-TEST_F(PaintPreviewUtilsRenderViewHostTest, CaptureSingleFrameAndDelete) {
-  content::NavigationSimulator::NavigateAndCommitFromBrowser(
-      web_contents(), GURL("http://www.example.com"));
-  auto* contents = content::WebContents::FromRenderFrameHost(main_rfh());
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  MockPaintPreviewRecorder service;
-  service.SetResponseStatus(mojom::PaintPreviewStatus::kOk);
-  OverrideInterface(&service);
-
-  base::RunLoop loop;
-  Capture(contents,
-          base::BindOnce(
-              [](base::OnceClosure quit,
-                 const base::Optional<base::FilePath>& maybe_zip_path) {
-                EXPECT_TRUE(maybe_zip_path.has_value());
-                const base::FilePath& zip_path = maybe_zip_path.value();
-                {
-                  base::ScopedAllowBlockingForTesting scope;
-                  EXPECT_FALSE(base::PathExists(zip_path));
-                  EXPECT_FALSE(base::DirectoryExists(zip_path.DirName()));
-                }
-                std::move(quit).Run();
-              },
-              loop.QuitClosure()),
-          false);
-  loop.Run();
-
-  auto entries = ukm_recorder.GetEntriesByName(
-      ukm::builders::PaintPreviewCapture::kEntryName);
-  EXPECT_EQ(2U, entries.size());
-}
-
-TEST_F(PaintPreviewUtilsRenderViewHostTest, SingleFrameFailure) {
-  content::NavigationSimulator::NavigateAndCommitFromBrowser(
-      web_contents(), GURL("http://www.example.com"));
-  auto* contents = content::WebContents::FromRenderFrameHost(main_rfh());
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  MockPaintPreviewRecorder service;
-  service.SetResponseStatus(mojom::PaintPreviewStatus::kFailed);
-  OverrideInterface(&service);
-
-  base::RunLoop loop;
-  Capture(contents,
-          base::BindOnce(
-              [](base::OnceClosure quit,
-                 const base::Optional<base::FilePath>& path) {
-                EXPECT_FALSE(path.has_value());
-                std::move(quit).Run();
-              },
-              loop.QuitClosure()),
-          false);
-  loop.Run();
-
-  auto entries = ukm_recorder.GetEntriesByName(
-      ukm::builders::PaintPreviewCapture::kEntryName);
-  EXPECT_EQ(0U, entries.size());
-}
-
-}  // namespace paint_preview
diff --git a/components/paint_preview/features/features.cc b/components/paint_preview/features/features.cc
index e236213..65acbda 100644
--- a/components/paint_preview/features/features.cc
+++ b/components/paint_preview/features/features.cc
@@ -8,9 +8,6 @@
 
 namespace paint_preview {
 
-const base::Feature kPaintPreviewCaptureExperiment{
-    "PaintPreviewCaptureExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kPaintPreviewDemo{"PaintPreviewDemo",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/components/paint_preview/features/features.h b/components/paint_preview/features/features.h
index 34953b0..35c50ee 100644
--- a/components/paint_preview/features/features.h
+++ b/components/paint_preview/features/features.h
@@ -11,13 +11,6 @@
 
 // IMPORTANT: Please keep this file in alphabetical order.
 
-// Used to enable the paint preview capture experiment on Android. If enabled,
-// paint preview capture will be triggered for a fraction of page loads, with
-// accordance to a probability threshold that is set by a field trial param.
-// Metrics for the capture are logged and the resulting paint preview is then
-// deleted.
-extern const base::Feature kPaintPreviewCaptureExperiment;
-
 // Used to enable a main menu item on Android that captures and displays a paint
 // preview for the current page. The paint preview UI will be dismissed on back
 // press and all associated stored files deleted. This intended to test whether
diff --git a/components/paint_preview/player/android/BUILD.gn b/components/paint_preview/player/android/BUILD.gn
index 3ac2aade..87d66b85 100644
--- a/components/paint_preview/player/android/BUILD.gn
+++ b/components/paint_preview/player/android/BUILD.gn
@@ -52,6 +52,7 @@
     "java/src/org/chromium/components/paintpreview/player/PaintPreviewFrame.java",
     "java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegate.java",
     "java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegateImpl.java",
+    "java/src/org/chromium/components/paintpreview/player/PlayerGestureListener.java",
     "java/src/org/chromium/components/paintpreview/player/PlayerManager.java",
     "java/src/org/chromium/components/paintpreview/player/PlayerSwipeRefreshHandler.java",
     "java/src/org/chromium/components/paintpreview/player/PlayerUserActionRecorder.java",
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegate.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegate.java
index 578554ed..fe73924 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegate.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegate.java
@@ -9,6 +9,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.UnguessableToken;
+import org.chromium.url.GURL;
 
 /**
  * Used for communicating with the Paint Preview delegate for requesting new bitmaps and forwarding
@@ -32,8 +33,9 @@
      * @param frameGuid The GUID of the frame.
      * @param x The x coordinate of the click event, relative to the frame.
      * @param y The y coordinate of the click event, relative to the frame.
+     * @return The URL that was clicked on. Null if there are no URLs.
      */
-    void onClick(UnguessableToken frameGuid, int x, int y);
+    GURL onClick(UnguessableToken frameGuid, int x, int y);
 
     /**
      * Sets whether to compress the directory when closing the player.
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegateImpl.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegateImpl.java
index 75316dc..4577b31 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegateImpl.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerCompositorDelegateImpl.java
@@ -6,6 +6,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Rect;
+import android.text.TextUtils;
 
 import org.chromium.base.Callback;
 import org.chromium.base.UnguessableToken;
@@ -35,9 +36,8 @@
 
     PlayerCompositorDelegateImpl(NativePaintPreviewServiceProvider service, GURL url,
             String directoryKey, @Nonnull CompositorListener compositorListener,
-            @Nonnull LinkClickHandler linkClickHandler, Runnable compositorErrorCallback) {
+            Runnable compositorErrorCallback) {
         mCompositorListener = compositorListener;
-        mLinkClickHandler = linkClickHandler;
         if (service != null && service.getNativeService() != 0) {
             mNativePlayerCompositorDelegate = PlayerCompositorDelegateImplJni.get().initialize(this,
                     service.getNativeService(), url.getSpec(), directoryKey,
@@ -96,13 +96,16 @@
     }
 
     @Override
-    public void onClick(UnguessableToken frameGuid, int x, int y) {
+    public GURL onClick(UnguessableToken frameGuid, int x, int y) {
         if (mNativePlayerCompositorDelegate == 0) {
-            return;
+            return null;
         }
 
-        PlayerCompositorDelegateImplJni.get().onClick(
+        String url = PlayerCompositorDelegateImplJni.get().onClick(
                 mNativePlayerCompositorDelegate, frameGuid, x, y);
+        if (TextUtils.isEmpty(url)) return null;
+
+        return new GURL(url);
     }
 
     @Override
@@ -115,12 +118,6 @@
                 mNativePlayerCompositorDelegate, compressOnClose);
     }
 
-    @CalledByNative
-    public void onLinkClicked(String url) {
-        PlayerUserActionRecorder.recordLinkClick();
-        mLinkClickHandler.onLinkClicked(new GURL(url));
-    }
-
     void destroy() {
         if (mNativePlayerCompositorDelegate == 0) {
             return;
@@ -138,8 +135,8 @@
         void requestBitmap(long nativePlayerCompositorDelegateAndroid, UnguessableToken frameGuid,
                 Callback<Bitmap> bitmapCallback, Runnable errorCallback, float scaleFactor,
                 int clipX, int clipY, int clipWidth, int clipHeight);
-        void onClick(long nativePlayerCompositorDelegateAndroid, UnguessableToken frameGuid, int x,
-                int y);
+        String onClick(long nativePlayerCompositorDelegateAndroid, UnguessableToken frameGuid,
+                int x, int y);
         void setCompressOnClose(
                 long nativePlayerCompositorDelegateAndroid, boolean compressOnClose);
     }
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerGestureListener.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerGestureListener.java
new file mode 100644
index 0000000..4ef39a9c
--- /dev/null
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerGestureListener.java
@@ -0,0 +1,56 @@
+// 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.components.paintpreview.player;
+
+import org.chromium.url.GURL;
+
+/**
+ * Records metrics and handles player-wide (as opposed to per-frame) logic related to touch
+ * gestures.
+ */
+public class PlayerGestureListener {
+    private Runnable mUserInteractionCallback;
+    private LinkClickHandler mLinkClickHandler;
+
+    public PlayerGestureListener(
+            LinkClickHandler linkClickHandler, Runnable userInteractionCallback) {
+        mLinkClickHandler = linkClickHandler;
+        mUserInteractionCallback = userInteractionCallback;
+    }
+
+    /**
+     * Called when a tap gesture happens in the player.
+     * @param url The GURL of the tapped link. If there are no links in the tapped region, this will
+     *            be null.
+     */
+    public void onTap(GURL url) {
+        if (url != null && mLinkClickHandler != null) {
+            mLinkClickHandler.onLinkClicked(url);
+            PlayerUserActionRecorder.recordLinkClick();
+            return;
+        }
+
+        PlayerUserActionRecorder.recordUnconsumedTap();
+    }
+
+    public void onLongPress() {
+        PlayerUserActionRecorder.recordLongPress();
+    }
+
+    public void onFling() {
+        if (mUserInteractionCallback != null) mUserInteractionCallback.run();
+        PlayerUserActionRecorder.recordFling();
+    }
+
+    public void onScroll() {
+        if (mUserInteractionCallback != null) mUserInteractionCallback.run();
+        PlayerUserActionRecorder.recordScroll();
+    }
+
+    public void onScale(boolean didFinish) {
+        if (mUserInteractionCallback != null) mUserInteractionCallback.run();
+        if (didFinish) PlayerUserActionRecorder.recordZoom();
+    }
+}
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerManager.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerManager.java
index b1eec880..19a89d00d 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerManager.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerManager.java
@@ -35,9 +35,9 @@
     private PlayerFrameCoordinator mRootFrameCoordinator;
     private FrameLayout mHostView;
     private Runnable mViewReadyCallback;
-    private Runnable mUserInteractionCallback;
     private static final String sInitEvent = "paint_preview PlayerManager init";
     private PlayerSwipeRefreshHandler mPlayerSwipeRefreshHandler;
+    private PlayerGestureListener mPlayerGestureListener;
     private boolean mIgnoreInitialScrollOffset;
 
     /**
@@ -65,16 +65,17 @@
         TraceEvent.startAsync(sInitEvent, hashCode());
         mContext = context;
         mDelegate = new PlayerCompositorDelegateImpl(nativePaintPreviewServiceProvider, url,
-                directoryKey, this::onCompositorReady, linkClickHandler, compositorErrorCallback);
+                directoryKey, this::onCompositorReady, compositorErrorCallback);
         mHostView = new FrameLayout(mContext);
         if (refreshCallback != null) {
             mPlayerSwipeRefreshHandler = new PlayerSwipeRefreshHandler(mContext, refreshCallback);
         }
+        mPlayerGestureListener =
+                new PlayerGestureListener(linkClickHandler, userInteractionCallback);
         mHostView.setLayoutParams(
                 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
         mHostView.setBackgroundColor(backgroundColor);
         mViewReadyCallback = viewReadyCallback;
-        mUserInteractionCallback = userInteractionCallback;
         mIgnoreInitialScrollOffset = ignoreInitialScrollOffset;
     }
 
@@ -93,7 +94,7 @@
         mRootFrameCoordinator = new PlayerFrameCoordinator(mContext, mDelegate, rootFrame.getGuid(),
                 rootFrame.getContentWidth(), rootFrame.getContentHeight(),
                 rootFrame.getInitialScrollX(), rootFrame.getInitialScrollY(), true,
-                mPlayerSwipeRefreshHandler, mUserInteractionCallback);
+                mPlayerSwipeRefreshHandler, mPlayerGestureListener);
         buildSubFrameCoordinators(mRootFrameCoordinator, rootFrame);
         mHostView.addView(mRootFrameCoordinator.getView(),
                 new FrameLayout.LayoutParams(
@@ -162,7 +163,7 @@
             PlayerFrameCoordinator childCoordinator = new PlayerFrameCoordinator(mContext,
                     mDelegate, childFrame.getGuid(), childFrame.getContentWidth(),
                     childFrame.getContentHeight(), childFrame.getInitialScrollX(),
-                    childFrame.getInitialScrollY(), false, null, mUserInteractionCallback);
+                    childFrame.getInitialScrollY(), false, null, mPlayerGestureListener);
             buildSubFrameCoordinators(childCoordinator, childFrame);
             frameCoordinator.addSubFrame(childCoordinator, frame.getSubFrameClips()[i]);
         }
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerUserActionRecorder.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerUserActionRecorder.java
index 99dbb71..2726cf32 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerUserActionRecorder.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerUserActionRecorder.java
@@ -10,11 +10,13 @@
 import java.util.Map;
 
 /** Helper class for recording paint preview user actions. */
-public class PlayerUserActionRecorder {
+class PlayerUserActionRecorder {
     private static final String ACTION_FLING = "PaintPreview.Player.Flung";
     private static final String ACTION_SCROLL = "PaintPreview.Player.Scrolled";
     private static final String ACTION_ZOOM = "PaintPreview.Player.Zoomed";
     private static final String ACTION_LINK_CLICK = "PaintPreview.Player.LinkClicked";
+    private static final String ACTION_UNCONSUMED_TAP = "PaintPreview.Player.UnconsumedTap";
+    private static final String ACTION_LONG_PRESS = "PaintPreview.Player.LongPress";
 
     private static final long NO_RECORD_WINDOW_MS = (long) (.5 * 1000);
     private static Map<String, Long> sLastRecordMap = new HashMap<>();
@@ -50,4 +52,12 @@
     public static void recordLinkClick() {
         RecordUserAction.record(ACTION_LINK_CLICK);
     }
+
+    public static void recordUnconsumedTap() {
+        RecordUserAction.record(ACTION_UNCONSUMED_TAP);
+    }
+
+    public static void recordLongPress() {
+        RecordUserAction.record(ACTION_LONG_PRESS);
+    }
 }
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java
index 0f6b30f..829bb28 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java
@@ -15,6 +15,7 @@
 import org.chromium.base.UnguessableToken;
 import org.chromium.components.paintpreview.player.OverscrollHandler;
 import org.chromium.components.paintpreview.player.PlayerCompositorDelegate;
+import org.chromium.components.paintpreview.player.PlayerGestureListener;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
@@ -32,14 +33,13 @@
     public PlayerFrameCoordinator(Context context, PlayerCompositorDelegate compositorDelegate,
             UnguessableToken frameGuid, int contentWidth, int contentHeight, int initialScrollX,
             int initialScrollY, boolean canDetectZoom,
-            @Nullable OverscrollHandler overscrollHandler,
-            @Nullable Runnable userInteractionCallback) {
+            @Nullable OverscrollHandler overscrollHandler, PlayerGestureListener gestureHandler) {
         PropertyModel model = new PropertyModel.Builder(PlayerFrameProperties.ALL_KEYS).build();
         OverScroller scroller = new OverScroller(context);
         scroller.setFriction(ViewConfiguration.getScrollFriction() / 2);
         mMediator = new PlayerFrameMediator(model, compositorDelegate, new PlayerFrameViewport(),
-                scroller, userInteractionCallback, frameGuid, contentWidth, contentHeight,
-                initialScrollX, initialScrollY);
+                scroller, gestureHandler, frameGuid, contentWidth, contentHeight, initialScrollX,
+                initialScrollY);
         mView = new PlayerFrameView(context, canDetectZoom, mMediator);
         if (overscrollHandler != null) {
             mMediator.setOverscrollHandler(overscrollHandler);
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameGestureDetector.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameGestureDetector.java
index 22929bf..a04801f 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameGestureDetector.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameGestureDetector.java
@@ -85,7 +85,7 @@
 
     @Override
     public boolean onSingleTapUp(MotionEvent e) {
-        mPlayerFrameViewDelegate.onClick((int) e.getX(), (int) e.getY());
+        mPlayerFrameViewDelegate.onTap((int) e.getX(), (int) e.getY());
         return true;
     }
 
@@ -115,7 +115,9 @@
     }
 
     @Override
-    public void onLongPress(MotionEvent e) {}
+    public void onLongPress(MotionEvent e) {
+        mPlayerFrameViewDelegate.onLongPress((int) e.getX(), (int) e.getY());
+    }
 
     @Override
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java
index 0745130..3b20e0f 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java
@@ -11,13 +11,14 @@
 import android.view.View;
 import android.widget.OverScroller;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.UnguessableToken;
 import org.chromium.components.paintpreview.player.OverscrollHandler;
 import org.chromium.components.paintpreview.player.PlayerCompositorDelegate;
+import org.chromium.components.paintpreview.player.PlayerGestureListener;
 import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.url.GURL;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -73,10 +74,12 @@
 
     private final PlayerFrameBitmapStateController mBitmapStateController;
 
+    private PlayerGestureListener mGestureListener;
+
     PlayerFrameMediator(PropertyModel model, PlayerCompositorDelegate compositorDelegate,
             PlayerFrameViewport viewport, OverScroller scroller,
-            @Nullable Runnable userInteractionCallback, UnguessableToken frameGuid,
-            int contentWidth, int contentHeight, int initialScrollX, int initialScrollY) {
+            PlayerGestureListener gestureListener, UnguessableToken frameGuid, int contentWidth,
+            int contentHeight, int initialScrollX, int initialScrollY) {
         mModel = model;
         mModel.set(PlayerFrameProperties.SCALE_MATRIX, mBitmapScaleMatrix);
 
@@ -86,10 +89,11 @@
         mContentSize = new Size(contentWidth, contentHeight);
         mBitmapStateController = new PlayerFrameBitmapStateController(
                 mGuid, mViewport, mContentSize, mCompositorDelegate, this);
-        mScrollController = new PlayerFrameScrollController(
-                scroller, mViewport, mContentSize, this, userInteractionCallback);
+        mScrollController = new PlayerFrameScrollController(scroller, mViewport, mContentSize, this,
+                gestureListener::onScroll, gestureListener::onFling);
         mScaleController = new PlayerFrameScaleController(
-                mViewport, mContentSize, mBitmapScaleMatrix, this, userInteractionCallback);
+                mViewport, mContentSize, mBitmapScaleMatrix, this, gestureListener::onScale);
+        mGestureListener = gestureListener;
         mViewport.offset(initialScrollX, initialScrollY);
         mViewport.setScale(0f);
     }
@@ -191,13 +195,19 @@
     }
 
     @Override
-    public void onClick(int x, int y) {
+    public void onTap(int x, int y) {
         // x and y are in the View's coordinate system (scaled). This needs to be adjusted to the
         // absolute coordinate system for hit testing.
         final float scaleFactor = mViewport.getScale();
-        mCompositorDelegate.onClick(mGuid,
+        GURL url = mCompositorDelegate.onClick(mGuid,
                 Math.round((float) (mViewport.getTransX() + x) / scaleFactor),
                 Math.round((float) (mViewport.getTransY() + y) / scaleFactor));
+        mGestureListener.onTap(url);
+    }
+
+    @Override
+    public void onLongPress(int x, int y) {
+        mGestureListener.onLongPress();
     }
 
     // PlayerFrameMediatorDelegate
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleController.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleController.java
index 759b628..97f069f7 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleController.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleController.java
@@ -10,7 +10,7 @@
 
 import androidx.annotation.Nullable;
 
-import org.chromium.components.paintpreview.player.PlayerUserActionRecorder;
+import org.chromium.base.Callback;
 
 /**
  * Handles scaling of the top level frame for the paint preview player.
@@ -27,16 +27,16 @@
     private final Matrix mBitmapScaleMatrix;
     /** Interface for calling shared methods on the mediator. */
     private final PlayerFrameMediatorDelegate mMediatorDelegate;
-    private final Runnable mUserInteractionCallback;
+    private final Callback<Boolean> mOnScaleListener;
 
     PlayerFrameScaleController(PlayerFrameViewport viewport, Size contentSize,
             Matrix bitmapScaleMatrix, PlayerFrameMediatorDelegate mediatorDelegate,
-            @Nullable Runnable userInteractionCallback) {
+            @Nullable Callback<Boolean> onScaleListener) {
         mViewport = viewport;
         mContentSize = contentSize;
         mBitmapScaleMatrix = bitmapScaleMatrix;
         mMediatorDelegate = mediatorDelegate;
-        mUserInteractionCallback = userInteractionCallback;
+        mOnScaleListener = onScaleListener;
     }
 
     /**
@@ -156,9 +156,8 @@
             bitmapScaleMatrixValues[Matrix.MTRANS_Y] += deltaY;
             mBitmapScaleMatrix.setValues(bitmapScaleMatrixValues);
         }
-
         mMediatorDelegate.setBitmapScaleMatrix(mBitmapScaleMatrix, correctedAggregateScaleFactor);
-        if (mUserInteractionCallback != null) mUserInteractionCallback.run();
+        if (mOnScaleListener != null) mOnScaleListener.onResult(false);
         return true;
     }
 
@@ -174,8 +173,8 @@
         mMediatorDelegate.resetScaleFactorOfAllSubframes();
         mMediatorDelegate.updateVisuals(true);
         mMediatorDelegate.forceRedrawVisibleSubframes();
-        PlayerUserActionRecorder.recordZoom();
         mUncommittedScaleFactor = 0f;
+        if (mOnScaleListener != null) mOnScaleListener.onResult(true);
         return true;
     }
 }
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollController.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollController.java
index 25519375..ceb3d4ab 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollController.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollController.java
@@ -12,7 +12,6 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.components.paintpreview.player.OverscrollHandler;
-import org.chromium.components.paintpreview.player.PlayerUserActionRecorder;
 
 /**
  * Handles scrolling of a frame for the paint preview player.
@@ -30,16 +29,18 @@
     private final Size mContentSize;
     /** Interface for calling shared methods on the mediator. */
     private final PlayerFrameMediatorDelegate mMediatorDelegate;
-    private final Runnable mUserInteractionCallback;
+    private final Runnable mOnScrollListener;
+    private final Runnable mOnFlingListener;
 
     PlayerFrameScrollController(OverScroller scroller, PlayerFrameViewport viewport,
             Size contentSize, PlayerFrameMediatorDelegate mediatorDelegate,
-            @Nullable Runnable userInteractionCallback) {
+            @Nullable Runnable onScrollListener, @Nullable Runnable onFlingListener) {
         mScroller = scroller;
         mViewport = viewport;
         mContentSize = contentSize;
         mMediatorDelegate = mediatorDelegate;
-        mUserInteractionCallback = userInteractionCallback;
+        mOnScrollListener = onScrollListener;
+        mOnFlingListener = onFlingListener;
     }
 
     /**
@@ -58,7 +59,7 @@
     public boolean scrollBy(float distanceX, float distanceY) {
         mScroller.forceFinished(true);
         boolean result = scrollByInternal(distanceX, distanceY);
-        if (result) PlayerUserActionRecorder.recordScroll();
+        if (result && mOnScrollListener != null) mOnScrollListener.run();
         return result;
     }
 
@@ -78,8 +79,8 @@
                 scaledContentWidth - viewportRect.width(), 0,
                 scaledContentHeight - viewportRect.height());
 
+        if (!mScroller.isFinished() && mOnFlingListener != null) mOnFlingListener.run();
         mScrollerHandler.post(this::handleFling);
-        if (!mScroller.isFinished()) PlayerUserActionRecorder.recordFling();
         return true;
     }
 
@@ -148,7 +149,6 @@
         mMediatorDelegate.offsetBitmapScaleMatrix(validDistanceX, validDistanceY);
         mViewport.offset(validDistanceX, validDistanceY);
         mMediatorDelegate.updateVisuals(false);
-        if (mUserInteractionCallback != null) mUserInteractionCallback.run();
         return true;
     }
 
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameViewDelegate.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameViewDelegate.java
index a0dfcd7..2140f33 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameViewDelegate.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameViewDelegate.java
@@ -38,7 +38,14 @@
      * @param x X coordinate of the point clicked.
      * @param y Y coordinate of the point clicked.
      */
-    void onClick(int x, int y);
+    void onTap(int x, int y);
+
+    /**
+     * Called when a long press gesture is performed.
+     * @param x X coordinate of the point clicked.
+     * @param y Y coordinate of the point clicked.
+     */
+    void onLongPress(int x, int y);
 
     /**
      * Called when a fling gesture is performed.
diff --git a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
index eee2ffda2..a2f593a 100644
--- a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
+++ b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
@@ -37,7 +37,9 @@
 import org.chromium.base.UnguessableToken;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.components.paintpreview.player.PlayerCompositorDelegate;
+import org.chromium.components.paintpreview.player.PlayerGestureListener;
 import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.url.GURL;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -59,7 +61,7 @@
     private TestPlayerCompositorDelegate mCompositorDelegate;
     private OverScroller mScroller;
     private boolean mHasUserInteraction;
-    private Runnable mUserInteractionCallback;
+    private PlayerGestureListener mGestureListener;
     private PlayerFrameViewport mViewport;
     private PlayerFrameMediator mMediator;
     private PlayerFrameBitmapStateController mBitmapStateController;
@@ -179,8 +181,9 @@
         }
 
         @Override
-        public void onClick(UnguessableToken frameGuid, int x, int y) {
+        public GURL onClick(UnguessableToken frameGuid, int x, int y) {
             mClickedPoints.add(new ClickedPoint(frameGuid, x, y));
+            return null;
         }
     }
 
@@ -203,10 +206,10 @@
         mModel = new PropertyModel.Builder(PlayerFrameProperties.ALL_KEYS).build();
         mCompositorDelegate = new TestPlayerCompositorDelegate();
         mScroller = new OverScroller(ContextUtils.getApplicationContext());
-        mUserInteractionCallback = () -> mHasUserInteraction = true;
+        mGestureListener = new PlayerGestureListener(null, () -> mHasUserInteraction = true);
         mViewport = new PlayerFrameViewport();
         mMediator = new PlayerFrameMediator(mModel, mCompositorDelegate, mViewport, mScroller,
-                mUserInteractionCallback, mFrameGuid, CONTENT_WIDTH, CONTENT_HEIGHT, 0, 0);
+                mGestureListener, mFrameGuid, CONTENT_WIDTH, CONTENT_HEIGHT, 0, 0);
         mBitmapStateController = mMediator.getBitmapStateControllerForTest();
     }
 
@@ -700,19 +703,19 @@
         List<ClickedPoint> expectedClickedPoints = new ArrayList<>();
 
         // No scrolling has happened yet.
-        mMediator.onClick(15, 26);
+        mMediator.onTap(15, 26);
         expectedClickedPoints.add(new ClickedPoint(mFrameGuid, 15, 26));
         Assert.assertEquals(expectedClickedPoints, mCompositorDelegate.mClickedPoints);
 
         // Scroll, and then click. The call to {@link PlayerFrameMediator} must account for the
         // scroll offset.
         mMediator.scrollBy(90, 100);
-        mMediator.onClick(70, 50);
+        mMediator.onTap(70, 50);
         expectedClickedPoints.add(new ClickedPoint(mFrameGuid, 160, 150));
         Assert.assertEquals(expectedClickedPoints, mCompositorDelegate.mClickedPoints);
 
         mMediator.scrollBy(-40, -60);
-        mMediator.onClick(30, 80);
+        mMediator.onTap(30, 80);
         expectedClickedPoints.add(new ClickedPoint(mFrameGuid, 80, 120));
         Assert.assertEquals(expectedClickedPoints, mCompositorDelegate.mClickedPoints);
     }
diff --git a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleControllerTest.java b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleControllerTest.java
index 6af7f50d..a47e217 100644
--- a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleControllerTest.java
+++ b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScaleControllerTest.java
@@ -20,6 +20,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import org.chromium.base.Callback;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
 /**
@@ -36,8 +37,7 @@
     private PlayerFrameScaleController mScaleController;
     @Mock
     private PlayerFrameMediatorDelegate mMediatorDelegateMock;
-    private boolean mHasUserInteraction;
-    private Runnable mUserInteractionCallback;
+    private boolean mDidScale;
 
     private class MatrixMatcher implements ArgumentMatcher<Matrix> {
         private Matrix mLeft;
@@ -55,13 +55,13 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mHasUserInteraction = false;
-        mUserInteractionCallback = () -> mHasUserInteraction = true;
+        mDidScale = false;
+        Callback<Boolean> mScaleListener = (Boolean didFinish) -> mDidScale = true;
         mViewport = new PlayerFrameViewport();
         mBitmapScaleMatrix = new Matrix();
         mScaleController =
                 new PlayerFrameScaleController(mViewport, new Size(CONTENT_WIDTH, CONTENT_HEIGHT),
-                        mBitmapScaleMatrix, mMediatorDelegateMock, mUserInteractionCallback);
+                        mBitmapScaleMatrix, mMediatorDelegateMock, mScaleListener);
         mScaleController.calculateInitialScaleFactor(CONTENT_WIDTH);
         mViewport.setScale(mScaleController.getInitialScaleFactor());
         mViewport.setSize(100, 100);
@@ -114,7 +114,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(2f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(2f, mViewport.getScale(), TOLERANCE);
@@ -137,7 +137,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(1f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(1f, mViewport.getScale(), TOLERANCE);
@@ -166,7 +166,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(2f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(2f, mViewport.getScale(), TOLERANCE);
@@ -190,7 +190,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(1.5f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(1.5f, mViewport.getScale(), TOLERANCE);
@@ -219,7 +219,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(1.5f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(1.5f, mViewport.getScale(), TOLERANCE);
@@ -256,7 +256,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(1.125f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(1.125f, mViewport.getScale(), TOLERANCE);
@@ -286,7 +286,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(2f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(2f, mViewport.getScale(), TOLERANCE);
@@ -310,7 +310,7 @@
         Assert.assertEquals(expectedBitmapMatrix, mBitmapScaleMatrix);
         inOrder.verify(mMediatorDelegateMock)
                 .setBitmapScaleMatrix(argThat(new MatrixMatcher(expectedBitmapMatrix)), eq(1.5f));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScale);
 
         Assert.assertTrue(mScaleController.scaleFinished(1f, 0, 0));
         Assert.assertEquals(1.5f, mViewport.getScale(), TOLERANCE);
diff --git a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollControllerTest.java b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollControllerTest.java
index e88ad33..5e076f8 100644
--- a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollControllerTest.java
+++ b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameScrollControllerTest.java
@@ -44,20 +44,21 @@
     private PlayerFrameMediatorDelegate mMediatorDelegateMock;
     @Mock
     private OverscrollHandler mOverscrollHandlerMock;
-    private Runnable mUserInteractionCallback;
-    private boolean mHasUserInteraction;
+    private boolean mDidScroll;
+    private boolean mDidFling;
     private PlayerFrameScrollController mScrollController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mScroller = new OverScroller(ContextUtils.getApplicationContext());
-        mHasUserInteraction = false;
-        mUserInteractionCallback = () -> mHasUserInteraction = true;
+        mDidScroll = false;
+        Runnable mOnScrollListener = () -> mDidScroll = true;
+        Runnable mOnFlingListener = () -> mDidFling = true;
         mViewport = new PlayerFrameViewport();
         mScrollController = new PlayerFrameScrollController(mScroller, mViewport,
-                new Size(CONTENT_WIDTH, CONTENT_HEIGHT), mMediatorDelegateMock,
-                mUserInteractionCallback);
+                new Size(CONTENT_WIDTH, CONTENT_HEIGHT), mMediatorDelegateMock, mOnScrollListener,
+                mOnFlingListener);
     }
 
     /**
@@ -74,7 +75,7 @@
         Assert.assertEquals(100f, mViewport.getTransX(), TOLERANCE);
         Assert.assertEquals(100f, mViewport.getTransY(), TOLERANCE);
         verify(mMediatorDelegateMock).updateVisuals(eq(false));
-        Assert.assertTrue(mHasUserInteraction);
+        Assert.assertTrue(mDidScroll);
     }
 
     /**
@@ -135,6 +136,7 @@
         mViewport.setSize(100, 100);
 
         Assert.assertTrue(mScrollController.onFling(100, 0));
+        Assert.assertTrue(mDidFling);
         ShadowLooper.runUiThreadTasks();
         Assert.assertTrue(mScroller.isFinished());
         Assert.assertEquals(mScroller.getFinalX(), mViewport.getTransX(), TOLERANCE);
diff --git a/components/paint_preview/player/android/player_compositor_delegate_android.cc b/components/paint_preview/player/android/player_compositor_delegate_android.cc
index 2fe40de..d6a7a92 100644
--- a/components/paint_preview/player/android/player_compositor_delegate_android.cc
+++ b/components/paint_preview/player/android/player_compositor_delegate_android.cc
@@ -249,7 +249,7 @@
   }
 }
 
-void PlayerCompositorDelegateAndroid::OnClick(
+ScopedJavaLocalRef<jstring> PlayerCompositorDelegateAndroid::OnClick(
     JNIEnv* env,
     const JavaParamRef<jobject>& j_frame_guid,
     jint j_x,
@@ -259,13 +259,11 @@
           env, j_frame_guid),
       gfx::Rect(static_cast<int>(j_x), static_cast<int>(j_y), 1U, 1U));
   if (res.empty())
-    return;
+    return base::android::ConvertUTF8ToJavaString(env, "");
   base::UmaHistogramBoolean("Browser.PaintPreview.Player.LinkClicked", true);
   // TODO(crbug/1061435): Resolve cases where there are multiple links.
   // For now just return the first in the list.
-  Java_PlayerCompositorDelegateImpl_onLinkClicked(
-      env, java_ref_,
-      base::android::ConvertUTF8ToJavaString(env, res[0]->spec()));
+  return base::android::ConvertUTF8ToJavaString(env, res[0]->spec());
 }
 
 void PlayerCompositorDelegateAndroid::SetCompressOnClose(
diff --git a/components/paint_preview/player/android/player_compositor_delegate_android.h b/components/paint_preview/player/android/player_compositor_delegate_android.h
index 434ea78..a4a4ab7 100644
--- a/components/paint_preview/player/android/player_compositor_delegate_android.h
+++ b/components/paint_preview/player/android/player_compositor_delegate_android.h
@@ -44,10 +44,11 @@
       jint j_clip_height);
 
   // Called from Java on touch event on a frame.
-  void OnClick(JNIEnv* env,
-               const base::android::JavaParamRef<jobject>& j_frame_guid,
-               jint j_x,
-               jint j_y);
+  base::android::ScopedJavaLocalRef<jstring> OnClick(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& j_frame_guid,
+      jint j_x,
+      jint j_y);
 
   // Called to set if compression should happen at close time.
   void SetCompressOnClose(JNIEnv* env, jboolean compress_on_close);
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index e7c77f7..ac3cde41 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -975,9 +975,6 @@
 
 void PasswordFormManager::CalculateFillingAssistanceMetric(
     const FormData& submitted_form) {
-  // TODO(https://crbug.com/918846): implement collecting all necessary data
-  // on iOS.
-#if not defined(OS_IOS)
   std::set<std::pair<base::string16, PasswordForm::Store>> saved_usernames;
   std::set<std::pair<base::string16, PasswordForm::Store>> saved_passwords;
 
@@ -994,7 +991,6 @@
       form_fetcher_->GetInteractionsStats(),
       client_->GetPasswordFeatureManager()
           ->ComputePasswordAccountStorageUsageLevel());
-#endif
 }
 
 bool PasswordFormManager::UsePossibleUsername(
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index c8aac7a8..758b6233 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -1802,13 +1802,7 @@
   EXPECT_GE(updated_form.date_last_used, kNow);
 }
 
-// TODO(https://crbug.com/918846): implement FillingAssistance metric on iOS.
-#if defined(OS_IOS)
-#define MAYBE_FillingAssistanceMetric DISABLED_FillingAssistanceMetric
-#else
-#define MAYBE_FillingAssistanceMetric FillingAssistanceMetric
-#endif
-TEST_P(PasswordFormManagerTest, MAYBE_FillingAssistanceMetric) {
+TEST_P(PasswordFormManagerTest, FillingAssistanceMetric) {
   SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
 
   // Simulate that the user fills the saved credentials manually.
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.cc b/components/password_manager/core/browser/password_form_metrics_recorder.cc
index 1c069c9..dbf5d39 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder.cc
+++ b/components/password_manager/core/browser/password_form_metrics_recorder.cc
@@ -16,6 +16,7 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
 #include "base/time/default_clock.h"
+#include "build/build_config.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
@@ -525,7 +526,9 @@
     is_mixed_content_form_ = true;
   }
 
+#if !defined(OS_IOS)
   filling_source_ = FillingSource::kNotFilled;
+#endif
   account_storage_usage_level_ = account_storage_usage_level;
 
   if (saved_passwords.empty() && is_blacklisted) {
@@ -562,12 +565,14 @@
     return;
   }
 
+#if !defined(OS_IOS)
   // At this point, the password was filled from at least one of the two stores,
   // so compute the filling source now.
   filling_source_ = ComputeFillingSource(
       username_password_state.password_exists_in_profile_store,
       username_password_state.password_exists_in_account_store);
   DCHECK_NE(*filling_source_, FillingSource::kNotFilled);
+#endif
 
   if (username_password_state.saved_username_typed) {
     filling_assistance_ = FillingAssistance::kUsernameTypedPasswordFilled;
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc b/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
index 240dee4..a95cade 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
+++ b/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/task_environment.h"
+#include "build/build_config.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/password_manager/core/browser/password_manager.h"
@@ -1115,6 +1116,7 @@
            PasswordFormMetricsRecorder::FillingAssistance::kAutomatic});
 }
 
+#if !defined(OS_IOS)
 struct FillingSourceTestCase {
   std::vector<TestCaseFieldInfo> fields;
 
@@ -1550,5 +1552,6 @@
         PasswordFormMetricsRecorder::FillingSource::kNotFilled, 1);
   }
 }
+#endif
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h
index f7f7e04..7b405e4 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.h
+++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -17,46 +17,52 @@
 
 namespace metrics_util {
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordBubble.DisplayDisposition"
 enum UIDisplayDisposition {
   AUTOMATIC_WITH_PASSWORD_PENDING = 0,
-  MANUAL_WITH_PASSWORD_PENDING,
-  MANUAL_MANAGE_PASSWORDS,
-  MANUAL_BLACKLISTED_OBSOLETE,  // obsolete.
-  AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION,
-  AUTOMATIC_CREDENTIAL_REQUEST_OBSOLETE,  // obsolete
-  AUTOMATIC_SIGNIN_TOAST,
-  MANUAL_WITH_PASSWORD_PENDING_UPDATE,
-  AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE,
-  MANUAL_GENERATED_PASSWORD_CONFIRMATION,
-  AUTOMATIC_SAVE_UNSYNCED_CREDENTIALS_LOCALLY,
-  AUTOMATIC_COMPROMISED_CREDENTIALS_REMINDER,
-  AUTOMATIC_MOVE_TO_ACCOUNT_STORE,
+  MANUAL_WITH_PASSWORD_PENDING = 1,
+  MANUAL_MANAGE_PASSWORDS = 2,
+  MANUAL_BLACKLISTED_OBSOLETE = 3,  // obsolete.
+  AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION = 4,
+  AUTOMATIC_CREDENTIAL_REQUEST_OBSOLETE = 5,  // obsolete
+  AUTOMATIC_SIGNIN_TOAST = 6,
+  MANUAL_WITH_PASSWORD_PENDING_UPDATE = 7,
+  AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE = 8,
+  MANUAL_GENERATED_PASSWORD_CONFIRMATION = 9,
+  AUTOMATIC_SAVE_UNSYNCED_CREDENTIALS_LOCALLY = 10,
+  AUTOMATIC_COMPROMISED_CREDENTIALS_REMINDER = 11,
+  AUTOMATIC_MOVE_TO_ACCOUNT_STORE = 12,
   NUM_DISPLAY_DISPOSITIONS,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordManager.UIDismissalReason"
 enum UIDismissalReason {
   // We use this to mean both "Bubble lost focus" and "No interaction with the
   // infobar".
   NO_DIRECT_INTERACTION = 0,
-  CLICKED_ACCEPT,
-  CLICKED_CANCEL,
-  CLICKED_NEVER,
-  CLICKED_MANAGE,
-  CLICKED_DONE_OBSOLETE,         // obsolete
-  CLICKED_UNBLACKLIST_OBSOLETE,  // obsolete.
-  CLICKED_OK_OBSOLETE,           // obsolete
-  CLICKED_CREDENTIAL_OBSOLETE,   // obsolete.
-  AUTO_SIGNIN_TOAST_TIMEOUT,
-  AUTO_SIGNIN_TOAST_CLICKED_OBSOLETE,  // obsolete.
-  CLICKED_BRAND_NAME_OBSOLETE,         // obsolete.
-  CLICKED_PASSWORDS_DASHBOARD,
+  CLICKED_ACCEPT = 1,
+  CLICKED_CANCEL = 2,
+  CLICKED_NEVER = 3,
+  CLICKED_MANAGE = 4,
+  CLICKED_DONE_OBSOLETE = 5,         // obsolete
+  CLICKED_UNBLACKLIST_OBSOLETE = 6,  // obsolete.
+  CLICKED_OK_OBSOLETE = 7,           // obsolete
+  CLICKED_CREDENTIAL_OBSOLETE = 8,   // obsolete.
+  AUTO_SIGNIN_TOAST_TIMEOUT = 9,
+  AUTO_SIGNIN_TOAST_CLICKED_OBSOLETE = 10,  // obsolete.
+  CLICKED_BRAND_NAME_OBSOLETE = 11,         // obsolete.
+  CLICKED_PASSWORDS_DASHBOARD = 12,
   NUM_UI_RESPONSES,
 };
 
 // Enum representing the different leak detection dialogs shown to the user.
 // Corresponds to LeakDetectionDialogType suffix in histograms.xml.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class LeakDialogType {
   // The user is asked to visit the Password Checkup.
   kCheckup = 0,
@@ -82,30 +88,36 @@
   kMaxValue = kClickedOk,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum FormDeserializationStatus {
-  LOGIN_DATABASE_SUCCESS,
-  LOGIN_DATABASE_FAILURE,
-  LIBSECRET_SUCCESS,
-  LIBSECRET_FAILURE,
-  GNOME_SUCCESS,
-  GNOME_FAILURE,
+  LOGIN_DATABASE_SUCCESS = 0,
+  LOGIN_DATABASE_FAILURE = 1,
+  LIBSECRET_SUCCESS = 2,
+  LIBSECRET_FAILURE = 3,
+  GNOME_SUCCESS = 4,
+  GNOME_FAILURE = 5,
   NUM_DESERIALIZATION_STATUSES
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordManager.PasswordSyncState"
 enum PasswordSyncState {
-  SYNCING_OK,
-  NOT_SYNCING_FAILED_READ,
-  NOT_SYNCING_DUPLICATE_TAGS,
-  NOT_SYNCING_SERVER_ERROR,
-  NOT_SYNCING_FAILED_CLEANUP,
-  NOT_SYNCING_FAILED_DECRYPTION,
-  NOT_SYNCING_FAILED_ADD,
-  NOT_SYNCING_FAILED_UPDATE,
-  NOT_SYNCING_FAILED_METADATA_PERSISTENCE,
+  SYNCING_OK = 0,
+  NOT_SYNCING_FAILED_READ = 1,
+  NOT_SYNCING_DUPLICATE_TAGS = 2,
+  NOT_SYNCING_SERVER_ERROR = 3,
+  NOT_SYNCING_FAILED_CLEANUP = 4,
+  NOT_SYNCING_FAILED_DECRYPTION = 5,
+  NOT_SYNCING_FAILED_ADD = 6,
+  NOT_SYNCING_FAILED_UPDATE = 7,
+  NOT_SYNCING_FAILED_METADATA_PERSISTENCE = 8,
   NUM_SYNC_STATES
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordManager.ApplySyncChangesState"
 enum class ApplySyncChangesState {
   kApplyOK = 0,
@@ -117,73 +129,86 @@
   kMaxValue = kApplyMetadataChangesFailed,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordGeneration.SubmissionEvent"
 enum PasswordSubmissionEvent {
-  PASSWORD_SUBMITTED,
-  PASSWORD_SUBMISSION_FAILED,
-  PASSWORD_NOT_SUBMITTED,
-  PASSWORD_OVERRIDDEN,
-  PASSWORD_USED,
-  GENERATED_PASSWORD_FORCE_SAVED,
+  PASSWORD_SUBMITTED = 0,
+  PASSWORD_SUBMISSION_FAILED = 1,
+  PASSWORD_NOT_SUBMITTED = 2,
+  PASSWORD_OVERRIDDEN = 3,
+  PASSWORD_USED = 4,
+  GENERATED_PASSWORD_FORCE_SAVED = 5,
   SUBMISSION_EVENT_ENUM_COUNT
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum AutoSigninPromoUserAction {
-  AUTO_SIGNIN_NO_ACTION,
-  AUTO_SIGNIN_TURN_OFF,
-  AUTO_SIGNIN_OK_GOT_IT,
+  AUTO_SIGNIN_NO_ACTION = 0,
+  AUTO_SIGNIN_TURN_OFF = 1,
+  AUTO_SIGNIN_OK_GOT_IT = 2,
   AUTO_SIGNIN_PROMO_ACTION_COUNT
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum AccountChooserUserAction {
-  ACCOUNT_CHOOSER_DISMISSED,
-  ACCOUNT_CHOOSER_CREDENTIAL_CHOSEN,
-  ACCOUNT_CHOOSER_SIGN_IN,
+  ACCOUNT_CHOOSER_DISMISSED = 0,
+  ACCOUNT_CHOOSER_CREDENTIAL_CHOSEN = 1,
+  ACCOUNT_CHOOSER_SIGN_IN = 2,
   ACCOUNT_CHOOSER_ACTION_COUNT
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordManager.Mediation{Silent,Optional,Required}"
 enum class CredentialManagerGetResult {
   // The promise is rejected.
-  kRejected,
+  kRejected = 0,
   // Auto sign-in is not allowed in the current context.
-  kNoneZeroClickOff,
+  kNoneZeroClickOff = 1,
   // No matching credentials found.
-  kNoneEmptyStore,
+  kNoneEmptyStore = 2,
   // User mediation required due to > 1 matching credentials.
-  kNoneManyCredentials,
+  kNoneManyCredentials = 3,
   // User mediation required due to the signed out state.
-  kNoneSignedOut,
+  kNoneSignedOut = 4,
   // User mediation required due to pending first run experience dialog.
-  kNoneFirstRun,
+  kNoneFirstRun = 5,
   // Return empty credential for whatever reason.
-  kNone,
+  kNone = 6,
   // Return a credential from the account chooser.
-  kAccountChooser,
+  kAccountChooser = 7,
   // User is auto signed in.
-  kAutoSignIn,
+  kAutoSignIn = 8,
   // No credentials are returned in incognito mode.
-  kNoneIncognito,
+  kNoneIncognito = 9,
   // No credentials are returned while autofill_assistant is running.
-  kNoneAutofillAssistant,
+  kNoneAutofillAssistant = 10,
   kMaxValue = kNoneAutofillAssistant,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum PasswordReusePasswordFieldDetected {
-  NO_PASSWORD_FIELD,
-  HAS_PASSWORD_FIELD,
+  NO_PASSWORD_FIELD = 0,
+  HAS_PASSWORD_FIELD = 1,
   PASSWORD_REUSE_PASSWORD_FIELD_DETECTED_COUNT
 };
 
-// Recorded into a UMA histogram, so order of enumerators should not be changed.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class SubmittedFormFrame {
-  MAIN_FRAME,
-  IFRAME_WITH_SAME_URL_AS_MAIN_FRAME,
-  IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME,
-  IFRAME_WITH_DIFFERENT_SIGNON_REALM,
+  MAIN_FRAME = 0,
+  IFRAME_WITH_SAME_URL_AS_MAIN_FRAME = 1,
+  IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME = 2,
+  IFRAME_WITH_DIFFERENT_SIGNON_REALM = 3,
   SUBMITTED_FORM_FRAME_COUNT
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordManager.AccessPasswordInSettings"
 enum AccessPasswordInSettingsEvent {
   ACCESS_PASSWORD_VIEWED = 0,
@@ -206,14 +231,16 @@
 // Specifies the type of PasswordFormManagers and derived classes to distinguish
 // the context in which a PasswordFormManager is being created and used.
 enum class CredentialSourceType {
-  kUnknown,
+  kUnknown = 0,
   // This is used for form based credential management (PasswordFormManager).
-  kPasswordManager,
+  kPasswordManager = 1,
   // This is used for credential management API based credential management
   // (CredentialManagerPasswordFormManager).
-  kCredentialManagementAPI
+  kCredentialManagementAPI = 2
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: PasswordManager.DeleteCorruptedPasswordsResult
 // Metrics: PasswordManager.DeleteUndecryptableLoginsReturnValue
 // A passwords is considered corrupted if it's stored locally using lost
@@ -255,6 +282,8 @@
   kMaxValue = SAVED_SYNC_PASSWORD_CHANGE_COUNT,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class IsSyncPasswordHashSaved {
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
@@ -287,6 +316,8 @@
   kMaxValue = kContextMenu,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metrics: "PasswordManager.CertificateErrorsWhileSeeingForms"
 enum class CertificateError {
   NONE = 0,
@@ -298,7 +329,8 @@
   COUNT
 };
 
-// Used in UMA histograms, please do NOT reorder.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metric: "PasswordManager.ReusedPasswordType".
 enum class PasswordType {
   // Passwords saved by password manager.
@@ -318,6 +350,8 @@
   PASSWORD_TYPE_COUNT
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class LinuxBackendMigrationStatus {
   // No migration was attempted (this value should not occur).
   kNotAttempted = 0,
@@ -339,14 +373,16 @@
   // Could not replace old database.
   kFailedReplace = 8,
   // Could not initialise the temporary encrypted database.
-  kFailedInitEncrypted,
+  kFailedInitEncrypted = 9,
   // Could not reset th temporary encrypted database.
-  kDeprecatedFailedRecreateEncrypted,
+  kDeprecatedFailedRecreateEncrypted = 10,
   // Could not add entries into the temporary encrypted database.
-  kFailedWriteToEncrypted,
+  kFailedWriteToEncrypted = 11,
   kMaxValue = kFailedWriteToEncrypted
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Type of the password drop-down shown on focus field.
 enum class PasswordDropdownState {
   // The passwords are listed and maybe the "Show all" button.
@@ -375,7 +411,8 @@
   kMaxValue = kResigninToUnlockAccountStore
 };
 
-// Used in UMA histograms, please do NOT reorder.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 // Metric: "KeyboardAccessory.GenerationDialogChoice.{Automatic, Manual}".
 enum class GenerationDialogChoice {
   // The user accepted the generated password.
@@ -390,23 +427,23 @@
 // histogram_suffixes in histograms.xml!
 enum class PasswordAccountStorageUserState {
   // Signed-out user (and no account storage opt-in exists).
-  kSignedOutUser,
+  kSignedOutUser = 0,
   // Signed-out user, but an account storage opt-in exists.
-  kSignedOutAccountStoreUser,
+  kSignedOutAccountStoreUser = 1,
   // Signed-in user, not opted in to the account storage (but will save
   // passwords to the account storage by default).
-  kSignedInUser,
+  kSignedInUser = 2,
   // Signed-in user, not opted in to the account storage, and has explicitly
   // chosen to save passwords only on the device.
-  kSignedInUserSavingLocally,
+  kSignedInUserSavingLocally = 3,
   // Signed-in user, opted in to the account storage, and saving passwords to
   // the account storage.
-  kSignedInAccountStoreUser,
+  kSignedInAccountStoreUser = 4,
   // Signed-in user and opted in to the account storage, but has chosen to save
   // passwords only on the device.
-  kSignedInAccountStoreUserSavingLocally,
+  kSignedInAccountStoreUserSavingLocally = 5,
   // Syncing user.
-  kSyncUser,
+  kSyncUser = 6,
 };
 
 // Metrics: PasswordManager.MoveToAccountStoreTrigger.
@@ -427,16 +464,17 @@
 
 // The usage level of the account-scoped password storage. This is essentially
 // a less-detailed version of PasswordAccountStorageUserState, for metrics that
-// don't need the fully-detailed breakdown. Always keep this enum in sync with
-// the corresponding histogram_suffixes in histograms.xml!
+// don't need the fully-detailed breakdown.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class PasswordAccountStorageUsageLevel {
   // The user is not using the account-scoped password storage. Either they're
   // not signed in, or they haven't opted in to the account storage.
-  kNotUsingAccountStorage,
+  kNotUsingAccountStorage = 0,
   // The user is signed in and has opted in to the account storage.
-  kUsingAccountStorage,
+  kUsingAccountStorage = 1,
   // The user has enabled Sync.
-  kSyncing,
+  kSyncing = 2,
 };
 std::string GetPasswordAccountStorageUsageLevelHistogramSuffix(
     PasswordAccountStorageUsageLevel usage_level);
diff --git a/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc b/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc
index 7a1d09f1..7c54e28 100644
--- a/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc
+++ b/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc
@@ -113,11 +113,9 @@
     public_key_ = builder_.GetPublicSigningKeyAsString();
 
     expected_policy_.Set("Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                         POLICY_SOURCE_CLOUD,
-                         std::make_unique<base::Value>("disabled"), nullptr);
+                         POLICY_SOURCE_CLOUD, base::Value("disabled"), nullptr);
     expected_policy_.Set("Second", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
-                         POLICY_SOURCE_CLOUD,
-                         std::make_unique<base::Value>("maybe"), nullptr);
+                         POLICY_SOURCE_CLOUD, base::Value("maybe"), nullptr);
   }
 
   void SetUp() override {
@@ -576,13 +574,11 @@
   PolicyBundle expected_bundle;
   expected_bundle.Get(kTestExtensionNS)
       .Set("Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-           POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("published"),
-           nullptr);
+           POLICY_SOURCE_CLOUD, base::Value("published"), nullptr);
   // The second policy should be invalid.
   expected_bundle.Get(kTestExtensionNS)
       .Set("Undeclared Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-           POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("not published"),
-           nullptr);
+           POLICY_SOURCE_CLOUD, base::Value("not published"), nullptr);
   expected_bundle.Get(kTestExtensionNS)
       .GetMutable("Undeclared Name")
       ->SetInvalid();
diff --git a/components/policy/core/common/policy_loader_win_unittest.cc b/components/policy/core/common/policy_loader_win_unittest.cc
index 8d6d9cd..e6adadf 100644
--- a/components/policy/core/common/policy_loader_win_unittest.cc
+++ b/components/policy/core/common/policy_loader_win_unittest.cc
@@ -453,8 +453,7 @@
   PolicyBundle expected;
   expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
       .Set(test_keys::kKeyString, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
-           POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>("hklm"),
-           nullptr);
+           POLICY_SOURCE_PLATFORM, base::Value("hklm"), nullptr);
   expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
       .GetMutable(test_keys::kKeyString)
       ->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
@@ -514,9 +513,9 @@
 
   PolicyBundle expected;
   PolicyMap& expected_policy = expected.Get(ns);
-  expected_policy.Set(
-      "a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
-      std::make_unique<base::Value>(kMachineMandatory), nullptr);
+  expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                      POLICY_SOURCE_PLATFORM, base::Value(kMachineMandatory),
+                      nullptr);
   expected_policy.GetMutable("a")->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected_policy.GetMutable("a")->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected_policy.GetMutable("a")->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
@@ -538,8 +537,8 @@
       std::move(a_conflict_3));
 
   expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                      POLICY_SOURCE_PLATFORM,
-                      std::make_unique<base::Value>(kUserMandatory), nullptr);
+                      POLICY_SOURCE_PLATFORM, base::Value(kUserMandatory),
+                      nullptr);
   expected_policy.GetMutable("b")->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected_policy.GetMutable("b")->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
 
@@ -555,8 +554,7 @@
       std::move(b_conflict_2));
 
   expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
-                      POLICY_SOURCE_PLATFORM,
-                      std::make_unique<base::Value>(kMachineRecommended),
+                      POLICY_SOURCE_PLATFORM, base::Value(kMachineRecommended),
                       nullptr);
   expected_policy.GetMutable("c")->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
 
@@ -567,8 +565,8 @@
       std::move(c_conflict_1));
 
   expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
-                      POLICY_SOURCE_PLATFORM,
-                      std::make_unique<base::Value>(kUserRecommended), nullptr);
+                      POLICY_SOURCE_PLATFORM, base::Value(kUserRecommended),
+                      nullptr);
   EXPECT_TRUE(Matches(expected));
 }
 
diff --git a/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc b/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc
index 5def498..3459c5fe 100644
--- a/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc
+++ b/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc
@@ -85,16 +85,15 @@
   PolicyBundle bundle;
   const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
   bundle.Get(chrome_ns).Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                            POLICY_SOURCE_CLOUD,
-                            std::make_unique<base::Value>("visible"), nullptr);
+                            POLICY_SOURCE_CLOUD, base::Value("visible"),
+                            nullptr);
 
   EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
   std::unique_ptr<PolicyBundle> delegate_bundle(new PolicyBundle);
   delegate_bundle->CopyFrom(bundle);
   delegate_bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
       .Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-           POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("not visible"),
-           nullptr);
+           POLICY_SOURCE_CLOUD, base::Value("not visible"), nullptr);
   mock_provider_.UpdatePolicy(std::move(delegate_bundle));
   Mock::VerifyAndClearExpectations(&observer_);
 
@@ -121,8 +120,7 @@
 TEST_F(SchemaRegistryTrackingPolicyProviderTest, SchemaReadyWithComponents) {
   PolicyMap policy_map;
   policy_map.Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                 POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("omg"),
-                 nullptr);
+                 POLICY_SOURCE_CLOUD, base::Value("omg"), nullptr);
   std::unique_ptr<PolicyBundle> bundle(new PolicyBundle);
   bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")).CopyFrom(policy_map);
   bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
@@ -170,8 +168,7 @@
 
   PolicyMap policy_map;
   policy_map.Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                 POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("omg"),
-                 nullptr);
+                 POLICY_SOURCE_CLOUD, base::Value("omg"), nullptr);
   // Chrome policy updates are visible even if the components aren't ready.
   EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
   mock_provider_.UpdateChromePolicy(policy_map);
@@ -209,8 +206,7 @@
   // Serve policy for |ns|.
   PolicyBundle platform_policy;
   platform_policy.Get(ns).Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                              POLICY_SOURCE_CLOUD,
-                              std::make_unique<base::Value>("omg"), nullptr);
+                              POLICY_SOURCE_CLOUD, base::Value("omg"), nullptr);
   std::unique_ptr<PolicyBundle> copy(new PolicyBundle);
   copy->CopyFrom(platform_policy);
   EXPECT_CALL(observer_, OnUpdatePolicy(_));
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index eb84519..0b1000b 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -127,6 +127,7 @@
   optional bool report_bluetooth_info = 22 [default = false];
   optional bool report_fan_info = 23 [default = false];
   optional bool report_vpd_info = 24 [default = false];
+  optional bool report_system_info = 25 [default = false];
 
   // Frequency to report device status, default to 3 hours.
   optional int64 device_status_frequency = 9 [default = 10800000];
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index 39a3a99..fdcf42a 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -1077,9 +1077,32 @@
   repeated ThermalInfo thermal_infos = 1;
 }
 
-// Status for various system-wide non-hardware elements.
+// Status about a system's various elements.
 message SystemStatus {
+  // The product SKU (stock keeping unit) number.
   optional string vpd_sku_number = 1;
+  // The date the device was first activated.
+  // Format: YYYY-WW.
+  optional string first_power_date = 2;
+  // The date the device was manufactured (finalized in factory).
+  // Format: YYYY-MM-DD.
+  optional string manufacture_date = 3;
+  // Contents of CrosConfig in /arc/build-properties/marketing-name. E.g. "HP
+  // Chromebook x360 14"
+  optional string marketing_name = 4;
+  // The BIOS version. E.g. "Google_Sarien.12200.58.0"
+  optional string bios_version = 5;
+  // The product name of the motherboard. E.g. "Sarien"
+  optional string board_name = 6;
+  // The version of the motherboard. E.g. "rev16"
+  optional string board_version = 7;
+  // The chassis type of the device. The values reported by chassis type are
+  // mapped in
+  // www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf.
+  // E.g. "9"
+  optional uint64 chassis_type = 8;
+  // The product name (model) of the system. E.g. "Sarien"
+  optional string product_name = 9;
 }
 
 // Status of a single C-state. C-states are various modes the CPU can transition
@@ -1316,7 +1339,8 @@
   // Status of various main board components.
   optional BoardStatus board_status = 27;
 
-  // Status for various system-wide non-hardware elements.
+  // Information about a system's various non-hardware elements. This includes
+  // information from cached VPD, CrosConfig, and DMI.
   optional SystemStatus system_status = 28;
 
   // Stateful Partition Information for user data.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index bb62bc0d..be7f3eb 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -873,6 +873,7 @@
         'ReportDeviceBluetoothInfo',
         'ReportDeviceFanInfo',
         'ReportDeviceVpdInfo',
+        'ReportDeviceSystemInfo',
         'ReportUploadFrequency',
         'ReportArcStatusEnabled',
         'HeartbeatEnabled',
@@ -8607,6 +8608,27 @@
       'arc_support': 'This policy has no effect on the logging done by Android.',
     },
     {
+      'name': 'ReportDeviceSystemInfo',
+      'owners': ['file://components/policy/resources/OWNERS'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome_os:86-'],
+      'supported_chrome_os_management': ['google_cloud'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+      },
+      'example_value': False,
+      'id': 741,
+      'caption': '''Report system info''',
+      'tags': ['admin-sharing'],
+      'desc': '''Report a device's system information.
+
+      If the policy is set to false or left unset, the information will not be reported.
+      If set to true, the device's system information will be reported.''',
+      'arc_support': 'This policy has no effect on the logging done by Android.',
+    },
+    {
       'name': 'ReportUploadFrequency',
       'owners': ['file://components/policy/resources/OWNERS'],
       'type': 'int',
@@ -18834,7 +18856,11 @@
       'tags': [],
       'desc': '''Setting the policy to True allows pages to show pop-ups while the pages unload.
 
-      Setting the policy to False or leaving it unset prevents pages from showing pop-ups while the pages unload.''',
+      Setting the policy to False or leaving it unset prevents pages from showing pop-ups while the pages unload.
+
+      This policy will be removed in Chrome 88.
+
+      See https://www.chromestatus.com/feature/5989473649164288.''',
     },
     {
       'name': 'DeviceWilcoDtcConfiguration',
@@ -22397,6 +22423,7 @@
     'ReportDeviceBluetoothInfo': 'device_reporting.report_bluetooth_info',
     'ReportDeviceFanInfo': 'device_reporting.report_fan_info',
     'ReportDeviceVpdInfo': 'device_reporting.report_vpd_info',
+    'ReportDeviceSystemInfo': 'device_reporting.report_system_info',
     'ReportUploadFrequency': 'device_reporting.device_status_frequency',
     'NetworkThrottlingEnabled': 'network_throttling.enabled',
     'NetworkThrottlingEnabled': 'network_throttling.upload_rate_kbits',
@@ -22856,6 +22883,7 @@
         'ReportDeviceBluetoothInfo',
         'ReportDeviceFanInfo',
         'ReportDeviceVpdInfo',
+        'ReportDeviceSystemInfo',
         'ReportUploadFrequency',
         'ReportArcStatusEnabled',
         'HeartbeatEnabled',
@@ -22927,6 +22955,6 @@
   ],
   'placeholders': [],
   'deleted_policy_ids': [412, 476, 546, 562, 569, 578],
-  'highest_id_currently_used': 740,
+  'highest_id_currently_used': 741,
   'highest_atomic_group_id_currently_used': 38
 }
diff --git a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
index 2cd283de..6958088 100644
--- a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
+++ b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
@@ -67,23 +67,19 @@
 
 // Prevent detached tabs from glitching when the window is partially offscreen.
 // See https://crbug.com/1095717 for details.
+// This is easy to get wrong so scope very tightly to only disallow large
+// vertical jumps.
 - (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen {
-  if (!screen)
-    screen = [NSScreen mainScreen];
-  // A small margin so that constraining kicks in before we're *all the way*
-  // to the edge of the screen.
-  static constexpr CGFloat kThreshold = 80;
-  NSRect screenFrame = [screen frame];
-  // Adjust if either the entire frame is offscreen, or the toolbar is
-  // cut off at the top.
-  if (NSMaxY(rect) - kThreshold < NSMinY(screenFrame) ||  // Below the screen.
-      NSMaxX(rect) - kThreshold < NSMinX(screenFrame) ||  // Left of the screen.
-      NSMinX(rect) + kThreshold >
-          NSMaxX(screenFrame) ||  // Right of the screen.
-      NSMaxY(rect) + kThreshold > NSMaxY(screenFrame)) {  // Top above screen.
-    return [super constrainFrameRect:rect toScreen:screen];
-  }
-  return rect;
+  NSRect proposed = [super constrainFrameRect:rect toScreen:screen];
+  // This boils down to: use the small threshold when we're not avoiding a
+  // Dock on the bottom, and the big threshold otherwise.
+  static constexpr CGFloat kBigThreshold = 200;
+  static constexpr CGFloat kSmallThreshold = 50;
+  const CGFloat yDelta = NSMaxY(proposed) - NSMaxY(rect);
+  if (yDelta > kBigThreshold ||
+      (yDelta > kSmallThreshold && NSMinY(proposed) == 0))
+    return rect;
+  return proposed;
 }
 
 // NSWindow (PrivateAPI) overrides.
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp
index aeb0a98..353af23 100644
--- a/components/security_interstitials_strings.grdp
+++ b/components/security_interstitials_strings.grdp
@@ -83,6 +83,12 @@
   </message>
 
   <!-- Lookalike URL without a suggested hostname -->
+  <message name="IDS_LOOKALIKE_URL_HEADING_NO_SUGGESTED_URL" desc="Large heading. Context: the error page that's shown when the requested URL might be trying to trick the user since it looks fake. This interstitial warns the user to not visit the site but doesn't suggest a safe site.">
+    Fake site ahead
+  </message>
+  <message name="IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH_NO_SUGGESTED_URL" desc="Main paragraph of an error message. Context: the error page that's shown when the requested URL might be trying to trick the user since it looks fake. This interstitial warns the user to not visit the site but doesn't suggest a safe site.">
+    Attackers sometimes mimic sites by making small, hard-to-see changes to the URL.
+  </message>
   <message name="IDS_LOOKALIKE_URL_BACK_TO_SAFETY" desc="The text for the button that takes the user back to the new tab page.">
     Back to safety
   </message>
@@ -90,7 +96,6 @@
     Close page
   </message>
 
-
   <!-- Clock errors -->
   <message name="IDS_CLOCK_ERROR_TITLE" desc="Tab title. Context: the browser can't load a page because the device's clock is wrong.">
     Clock error
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING_NO_SUGGESTED_URL.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING_NO_SUGGESTED_URL.png.sha1
new file mode 100644
index 0000000..b75eeb2
--- /dev/null
+++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING_NO_SUGGESTED_URL.png.sha1
@@ -0,0 +1 @@
+55253a1969cec4562c3a9c370259eddeeb0fc70b
\ No newline at end of file
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH_NO_SUGGESTED_URL.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH_NO_SUGGESTED_URL.png.sha1
new file mode 100644
index 0000000..b75eeb2
--- /dev/null
+++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH_NO_SUGGESTED_URL.png.sha1
@@ -0,0 +1 @@
+55253a1969cec4562c3a9c370259eddeeb0fc70b
\ No newline at end of file
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc
index fd86354..bd6ae636 100644
--- a/components/sync/driver/sync_driver_switches.cc
+++ b/components/sync/driver/sync_driver_switches.cc
@@ -64,4 +64,8 @@
 const base::Feature kProfileSyncServiceUsesThreadPool{
     "ProfileSyncServiceUsesThreadPool", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Stops honoring the Android master sync toggle.
+const base::Feature kDecoupleSyncFromAndroidMasterSync{
+    "DecoupleSyncFromAndroidMasterSync", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace switches
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h
index 1d23ec1..f2ae73ba 100644
--- a/components/sync/driver/sync_driver_switches.h
+++ b/components/sync/driver/sync_driver_switches.h
@@ -32,6 +32,7 @@
 extern const base::Feature kSyncWifiConfigurations;
 extern const base::Feature kSyncDeviceInfoInTransportMode;
 extern const base::Feature kProfileSyncServiceUsesThreadPool;
+extern const base::Feature kDecoupleSyncFromAndroidMasterSync;
 
 }  // namespace switches
 
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index ec6a3901..72a679e 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -240,6 +240,8 @@
     "resources/transferable_resource.h",
     "skia_helper.cc",
     "skia_helper.h",
+    "surfaces/aggregated_frame.cc",
+    "surfaces/aggregated_frame.h",
     "surfaces/child_local_surface_id_allocator.cc",
     "surfaces/child_local_surface_id_allocator.h",
     "surfaces/frame_sink_id.cc",
diff --git a/components/viz/common/quads/compositor_frame_metadata.h b/components/viz/common/quads/compositor_frame_metadata.h
index 06b680d..987c579c 100644
--- a/components/viz/common/quads/compositor_frame_metadata.h
+++ b/components/viz/common/quads/compositor_frame_metadata.h
@@ -7,7 +7,9 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <vector>
+
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
diff --git a/components/viz/common/surfaces/DEPS b/components/viz/common/surfaces/DEPS
index a04d4aa..2562eca 100644
--- a/components/viz/common/surfaces/DEPS
+++ b/components/viz/common/surfaces/DEPS
@@ -2,4 +2,5 @@
 
 include_rules = [
   "+mojo/public/cpp/bindings",
+  "+ui/latency/latency_info.h",
 ]
diff --git a/components/viz/common/surfaces/aggregated_frame.cc b/components/viz/common/surfaces/aggregated_frame.cc
new file mode 100644
index 0000000..5d36b08
--- /dev/null
+++ b/components/viz/common/surfaces/aggregated_frame.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/viz/common/surfaces/aggregated_frame.h"
+
+namespace viz {
+
+AggregatedFrame::AggregatedFrame() = default;
+AggregatedFrame::AggregatedFrame(AggregatedFrame&& other) = default;
+AggregatedFrame::~AggregatedFrame() = default;
+
+AggregatedFrame& AggregatedFrame::operator=(AggregatedFrame&& other) = default;
+
+}  // namespace viz
diff --git a/components/viz/common/surfaces/aggregated_frame.h b/components/viz/common/surfaces/aggregated_frame.h
new file mode 100644
index 0000000..3010cda
--- /dev/null
+++ b/components/viz/common/surfaces/aggregated_frame.h
@@ -0,0 +1,63 @@
+// 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_VIZ_COMMON_SURFACES_AGGREGATED_FRAME_H_
+#define COMPONENTS_VIZ_COMMON_SURFACES_AGGREGATED_FRAME_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/optional.h"
+#include "components/viz/common/delegated_ink_metadata.h"
+#include "components/viz/common/quads/render_pass.h"
+#include "components/viz/common/viz_common_export.h"
+#include "ui/gfx/display_color_spaces.h"
+#include "ui/latency/latency_info.h"
+
+namespace viz {
+
+class VIZ_COMMON_EXPORT AggregatedFrame {
+ public:
+  AggregatedFrame();
+  AggregatedFrame(AggregatedFrame&& other);
+  ~AggregatedFrame();
+
+  AggregatedFrame& operator=(AggregatedFrame&& other);
+
+  // The visible height of the top-controls. If the value is not set, then the
+  // visible height should be the same as in the latest submitted frame with a
+  // value set.
+  base::Optional<float> top_controls_visible_height;
+
+  // A list of latency info used for this frame.
+  std::vector<ui::LatencyInfo> latency_info;
+
+  // Indicates the content color usage for this frame.
+  gfx::ContentColorUsage content_color_usage = gfx::ContentColorUsage::kSRGB;
+
+  // Indicates whether any render passes have a copy output request.
+  bool has_copy_requests = false;
+
+  // Indicates whether this frame may contain video.
+  bool may_contain_video = false;
+
+  // Contains the metadata required for drawing a delegated ink trail onto the
+  // end of a rendered ink stroke. This should only be present when two
+  // conditions are met:
+  //   1. The JS API |updateInkTrailStartPoint| is used - This gathers the
+  //     metadata and puts it onto a compositor frame to be sent to viz.
+  //   2. This frame will not be submitted to the root surface - The browser UI
+  //     does not use this, and the frame must be contained within a
+  //     SurfaceDrawQuad.
+  // The ink trail created with this metadata will only last for a single frame
+  // before it disappears, regardless of whether or not the next frame contains
+  // delegated ink metadata.
+  std::unique_ptr<DelegatedInkMetadata> delegated_ink_metadata;
+
+  RenderPassList render_pass_list;
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_COMMON_SURFACES_AGGREGATED_FRAME_H_
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
index dcfc2efa..a98b3a0 100644
--- a/components/viz/host/host_frame_sink_manager.cc
+++ b/components/viz/host/host_frame_sink_manager.cc
@@ -291,6 +291,17 @@
   frame_sink_manager_->RequestCopyOfOutput(surface_id, std::move(request));
 }
 
+void HostFrameSinkManager::StartThrottling(
+    const std::vector<FrameSinkId>& frame_sink_ids,
+    base::TimeDelta interval) {
+  DCHECK_GT(interval, base::TimeDelta());
+  frame_sink_manager_->StartThrottling(frame_sink_ids, interval);
+}
+
+void HostFrameSinkManager::EndThrottling() {
+  frame_sink_manager_->EndThrottling();
+}
+
 void HostFrameSinkManager::AddHitTestRegionObserver(
     HitTestRegionObserver* observer) {
   observers_.AddObserver(observer);
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h
index 44cc99f..52ac3aa 100644
--- a/components/viz/host/host_frame_sink_manager.h
+++ b/components/viz/host/host_frame_sink_manager.h
@@ -171,6 +171,18 @@
   void RequestCopyOfOutput(const SurfaceId& surface_id,
                            std::unique_ptr<CopyOutputRequest> request);
 
+  // Starts throttling the frame sinks specified by |frame_sink_ids| and all
+  // their descendant sinks to send BeginFrames at an interval of |interval|.
+  // |interval| should be greater than zero. Calling this function before
+  // calling EndThrottling() to end a previous throttling operation will
+  // automatically end the previous operation before applying the current
+  // throttling operation.
+  void StartThrottling(const std::vector<FrameSinkId>& frame_sink_ids,
+                       base::TimeDelta interval);
+
+  // Ends throttling of all previously throttled frame sinks.
+  void EndThrottling();
+
   // Add/Remove an observer to receive notifications of when the host receives
   // new hit test data.
   void AddHitTestRegionObserver(HitTestRegionObserver* observer);
diff --git a/components/viz/host/host_frame_sink_manager_unittest.cc b/components/viz/host/host_frame_sink_manager_unittest.cc
index 2dbfb27..8574438 100644
--- a/components/viz/host/host_frame_sink_manager_unittest.cc
+++ b/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -94,6 +94,12 @@
                void(const FrameSinkId& parent, const FrameSinkId& child));
   MOCK_METHOD2(UnregisterFrameSinkHierarchy,
                void(const FrameSinkId& parent, const FrameSinkId& child));
+  MOCK_METHOD(void,
+              StartThrottling,
+              (const std::vector<FrameSinkId>& frame_sink_ids,
+               base::TimeDelta interval),
+              (override));
+  MOCK_METHOD(void, EndThrottling, (), (override));
 };
 
 }  // namespace
@@ -481,4 +487,14 @@
   FlushHostAndVerifyExpectations();
 }
 
+TEST_F(HostFrameSinkManagerTest, ThrottleFramePainting) {
+  const std::vector<FrameSinkId> frame_sink_ids{
+      FrameSinkId(1, 1), FrameSinkId(2, 2), FrameSinkId(3, 3)};
+  constexpr base::TimeDelta interval = base::TimeDelta::FromSeconds(1) / 10;
+  EXPECT_CALL(impl(), StartThrottling(frame_sink_ids, interval)).Times(1);
+  host().StartThrottling(frame_sink_ids, interval);
+  EXPECT_CALL(impl(), EndThrottling()).Times(1);
+  host().EndThrottling();
+  FlushHostAndVerifyExpectations();
+}
 }  // namespace viz
diff --git a/components/viz/service/display/damage_frame_annotator.cc b/components/viz/service/display/damage_frame_annotator.cc
index 78c99bd..d7205024 100644
--- a/components/viz/service/display/damage_frame_annotator.cc
+++ b/components/viz/service/display/damage_frame_annotator.cc
@@ -8,17 +8,17 @@
 #include <utility>
 
 #include "cc/base/math_util.h"
-#include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/debug_border_draw_quad.h"
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/shared_quad_state.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 
 namespace viz {
 
 DamageFrameAnnotator::DamageFrameAnnotator() = default;
 DamageFrameAnnotator::~DamageFrameAnnotator() = default;
 
-void DamageFrameAnnotator::AnnotateAggregatedFrame(CompositorFrame* frame) {
+void DamageFrameAnnotator::AnnotateAggregatedFrame(AggregatedFrame* frame) {
   DCHECK(frame);
   auto* root_render_pass = frame->render_pass_list.back().get();
 
diff --git a/components/viz/service/display/damage_frame_annotator.h b/components/viz/service/display/damage_frame_annotator.h
index cab64d7c..54179ac 100644
--- a/components/viz/service/display/damage_frame_annotator.h
+++ b/components/viz/service/display/damage_frame_annotator.h
@@ -14,7 +14,7 @@
 
 namespace viz {
 
-class CompositorFrame;
+class AggregatedFrame;
 class RenderPass;
 
 // Draws a red outline around the root RenderPasses damage rect.
@@ -24,7 +24,7 @@
   ~DamageFrameAnnotator() override;
 
   // SurfaceAggregator::FrameAnnotator implementation.
-  void AnnotateAggregatedFrame(CompositorFrame* frame) override;
+  void AnnotateAggregatedFrame(AggregatedFrame* frame) override;
 
  private:
   struct Highlight {
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 8fc0b76..fa9d1711 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -25,6 +25,7 @@
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/viz_utils.h"
 #include "components/viz/service/display/damage_frame_annotator.h"
 #include "components/viz/service/display/direct_renderer.h"
@@ -642,7 +643,7 @@
 
   base::ElapsedTimer aggregate_timer;
   aggregate_timer.Begin();
-  CompositorFrame frame;
+  AggregatedFrame frame;
   {
     FrameRateDecider::ScopedAggregate scoped_aggregate(
         frame_rate_decider_.get());
@@ -659,24 +660,24 @@
   // TODO(vikassoni) : Extend this capability to record whether a video frame is
   // inline or fullscreen.
   UMA_HISTOGRAM_ENUMERATION("Compositing.SurfaceAggregator.FrameContainsVideo",
-                            frame.metadata.may_contain_video
+                            frame.may_contain_video
                                 ? TypeOfVideoInFrame::kVideo
                                 : TypeOfVideoInFrame::kNoVideo);
 
-  if (frame.metadata.delegated_ink_metadata) {
+  if (frame.delegated_ink_metadata) {
     TRACE_EVENT_INSTANT1(
         "viz", "Delegated Ink Metadata was aggregated for DrawAndSwap.",
         TRACE_EVENT_SCOPE_THREAD, "ink metadata",
-        frame.metadata.delegated_ink_metadata->ToString());
+        frame.delegated_ink_metadata->ToString());
     // TODO(1052145): This metadata will be stored here and used to determine
     // which points should be drawn onto the back buffer (via Skia or OS APIs)
     // before being swapped onto the screen.
   }
 
 #if defined(OS_ANDROID)
-  bool wide_color_enabled = display_color_spaces_.GetOutputColorSpace(
-                                frame.metadata.content_color_usage, true) !=
-                            gfx::ColorSpace::CreateSRGB();
+  bool wide_color_enabled =
+      display_color_spaces_.GetOutputColorSpace(
+          frame.content_color_usage, true) != gfx::ColorSpace::CreateSRGB();
   if (wide_color_enabled != last_wide_color_enabled_) {
     client_->SetWideColorEnabled(wide_color_enabled);
     last_wide_color_enabled_ = wide_color_enabled;
@@ -698,13 +699,11 @@
   // Run callbacks early to allow pipelining and collect presented callbacks.
   damage_tracker_->RunDrawCallbacks();
 
-  frame.metadata.latency_info.insert(frame.metadata.latency_info.end(),
-                                     stored_latency_info_.begin(),
-                                     stored_latency_info_.end());
+  frame.latency_info.insert(frame.latency_info.end(),
+                            stored_latency_info_.begin(),
+                            stored_latency_info_.end());
   stored_latency_info_.clear();
-  bool have_copy_requests = false;
-  for (const auto& pass : frame.render_pass_list)
-    have_copy_requests |= !pass->copy_requests.empty();
+  bool have_copy_requests = frame.has_copy_requests;
 
   gfx::Size surface_size;
   bool have_damage = false;
@@ -749,8 +748,14 @@
         "Compositing.Display.Draw.Occlusion.Calculation.Time",
         draw_occlusion_timer.Elapsed().InMicroseconds());
 
-    bool disable_image_filtering =
-        frame.metadata.is_resourceless_software_draw_with_scroll_or_animation;
+    // TODO(vmpstr): This used to set to
+    // frame.metadata.is_resourceless_software_draw_with_scroll_or_animation
+    // from CompositedFrame. However, after changing this to AggregatedFrame, it
+    // seems that the value is never changed from the default false (i.e.
+    // SurfaceAggregator has no reference to
+    // is_resourceless_software_draw_with_scroll_or_animation). The TODO here is
+    // to clean up the code below or to figure out if this value is important.
+    bool disable_image_filtering = false;
     if (software_renderer_) {
       software_renderer_->SetDisablePictureQuadImageFiltering(
           disable_image_filtering);
@@ -806,18 +811,17 @@
     swapped_since_resize_ = true;
 
     ui::LatencyInfo::TraceIntermediateFlowEvents(
-        frame.metadata.latency_info,
+        frame.latency_info,
         perfetto::protos::pbzero::ChromeLatencyInfo::STEP_DRAW_AND_SWAP);
 
     cc::benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
     DirectRenderer::SwapFrameData swap_frame_data;
-    swap_frame_data.latency_info = std::move(frame.metadata.latency_info);
-    if (frame.metadata.top_controls_visible_height.has_value()) {
+    swap_frame_data.latency_info = std::move(frame.latency_info);
+    if (frame.top_controls_visible_height.has_value()) {
       swap_frame_data.top_controls_visible_height_changed =
           last_top_controls_visible_height_ !=
-          *frame.metadata.top_controls_visible_height;
-      last_top_controls_visible_height_ =
-          *frame.metadata.top_controls_visible_height;
+          *frame.top_controls_visible_height;
+      last_top_controls_visible_height_ = *frame.top_controls_visible_height;
     }
 
     // We must notify scheduler and increase |pending_swaps_| before calling
@@ -835,16 +839,15 @@
 
     if (have_damage) {
       // Do not store more than the allowed size.
-      if (ui::LatencyInfo::Verify(frame.metadata.latency_info,
-                                  "Display::DrawAndSwap")) {
-        stored_latency_info_.swap(frame.metadata.latency_info);
+      if (ui::LatencyInfo::Verify(frame.latency_info, "Display::DrawAndSwap")) {
+        stored_latency_info_.swap(frame.latency_info);
       }
     } else {
       // There was no damage. Terminate the latency info objects.
-      while (!frame.metadata.latency_info.empty()) {
-        auto& latency = frame.metadata.latency_info.back();
+      while (!frame.latency_info.empty()) {
+        auto& latency = frame.latency_info.back();
         latency.Terminate();
-        frame.metadata.latency_info.pop_back();
+        frame.latency_info.pop_back();
       }
     }
 
@@ -1018,7 +1021,7 @@
     scheduler_->SetNeedsOneBeginFrame(false);
 }
 
-void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
+void Display::RemoveOverdrawQuads(AggregatedFrame* frame) {
   if (frame->render_pass_list.empty())
     return;
 
diff --git a/components/viz/service/display/display.h b/components/viz/service/display/display.h
index 81194be..0fb1268 100644
--- a/components/viz/service/display/display.h
+++ b/components/viz/service/display/display.h
@@ -45,6 +45,7 @@
 }
 
 namespace viz {
+class AggregatedFrame;
 class DirectRenderer;
 class DisplayClient;
 class DisplayResourceProvider;
@@ -173,7 +174,7 @@
 
   void ForceImmediateDrawAndSwapIfPossible();
   void SetNeedsOneBeginFrame();
-  void RemoveOverdrawQuads(CompositorFrame* frame);
+  void RemoveOverdrawQuads(AggregatedFrame* frame);
 
   void SetSupportedFrameIntervals(std::vector<base::TimeDelta> intervals);
 
diff --git a/components/viz/service/display/display_perftest.cc b/components/viz/service/display/display_perftest.cc
index c9e77e4..9e7bcc851 100644
--- a/components/viz/service/display/display_perftest.cc
+++ b/components/viz/service/display/display_perftest.cc
@@ -13,6 +13,7 @@
 #include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/service/display/display.h"
 #include "components/viz/service/display/display_scheduler.h"
@@ -151,7 +152,7 @@
     auto reporter = SetUpRemoveOverdrawQuadReporter(story);
     reporter.AddResult(kMetricOverlapThroughputRunsPerS,
                        timer_.LapsPerSecond());
-    frame_ = CompositorFrame();
+    frame_ = AggregatedFrame{};
   }
 
   void CreateOverlapShareQuadStates(int shared_quad_state_count,
@@ -191,7 +192,7 @@
     auto reporter = SetUpRemoveOverdrawQuadReporter(story);
     reporter.AddResult(kMetricIsolatedThroughputRunsPerS,
                        timer_.LapsPerSecond());
-    frame_ = CompositorFrame();
+    frame_ = AggregatedFrame{};
   }
 
   void CreateIsolatedSharedQuadStates(int shared_quad_state_count,
@@ -240,7 +241,7 @@
     auto reporter = SetUpRemoveOverdrawQuadReporter(story);
     reporter.AddResult(kMetricPartialOverlapThroughputRunsPerS,
                        timer_.LapsPerSecond());
-    frame_ = CompositorFrame();
+    frame_ = AggregatedFrame{};
   }
 
   void CreatePartiallyOverlapSharedQuadStates(int shared_quad_state_count,
@@ -287,7 +288,7 @@
     auto reporter = SetUpRemoveOverdrawQuadReporter(story);
     reporter.AddResult(kMetricAdjacentThroughputRunsPerS,
                        timer_.LapsPerSecond());
-    frame_ = CompositorFrame();
+    frame_ = AggregatedFrame{};
   }
 
   void CreateAdjacentSharedQuadStates(int shared_quad_state_count,
@@ -313,7 +314,7 @@
 
  private:
   DebugRendererSettings debug_settings_;
-  CompositorFrame frame_;
+  AggregatedFrame frame_;
   base::LapTimer timer_;
   StubBeginFrameSource begin_frame_source_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc
index 3c7d0cb..1207561 100644
--- a/components/viz/service/display/display_unittest.cc
+++ b/components/viz/service/display/display_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/viz/service/display/display.h"
 
+#include <limits>
 #include <utility>
 
 #include "base/bind.h"
@@ -21,6 +22,7 @@
 #include "components/viz/common/quads/render_pass_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/service/display/direct_renderer.h"
@@ -917,10 +919,13 @@
   SetUpGpuDisplay(settings);
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
-  CompositorFrame frame = CompositorFrameBuilder()
-                              .AddDefaultRenderPass()
-                              .AddDefaultRenderPass()
-                              .Build();
+  CompositorFrame compositor_frame = CompositorFrameBuilder()
+                                         .AddDefaultRenderPass()
+                                         .AddDefaultRenderPass()
+                                         .Build();
+  AggregatedFrame frame;
+  frame.render_pass_list = std::move(compositor_frame.render_pass_list);
+
   bool is_clipped = false;
   bool are_contents_opaque = true;
   float opacity = 1.f;
@@ -967,10 +972,12 @@
   SetUpGpuDisplay(settings);
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
-  CompositorFrame frame = CompositorFrameBuilder()
-                              .AddDefaultRenderPass()
-                              .AddDefaultRenderPass()
-                              .Build();
+  CompositorFrame compositor_frame = CompositorFrameBuilder()
+                                         .AddDefaultRenderPass()
+                                         .AddDefaultRenderPass()
+                                         .Build();
+  AggregatedFrame frame;
+  frame.render_pass_list = std::move(compositor_frame.render_pass_list);
 
   bool is_clipped = false;
   bool are_contents_opaque = true;
@@ -1043,7 +1050,8 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
+
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(50, 50, 100, 100);
   gfx::Rect rect3(25, 25, 50, 100);
@@ -1265,7 +1273,8 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
+
   std::vector<gfx::Rect> rects;
   rects.emplace_back(0, 0, 100, 100);
   rects.emplace_back(150, 0, 150, 150);
@@ -1320,7 +1329,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   std::vector<gfx::Rect> rects;
   rects.emplace_back(0, 0, 100, 100);
   rects.emplace_back(150, 0, 150, 150);
@@ -1373,7 +1382,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(25, 25, 50, 50);
   gfx::Rect rect3(50, 50, 50, 25);
@@ -1504,7 +1513,7 @@
 
   // Rect 2, 3, 4 are contained in rect 1 only after applying the half scale
   // matrix. They are repetition of CompositorFrameWithOverlapDrawQuad.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(50, 50, 100, 100);
   gfx::Rect rect3(100, 100, 100, 50);
@@ -1772,7 +1781,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect(0, 0, 100, 100);
 
   SkScalar epsilon = 0.000000001f;
@@ -1882,7 +1891,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect(0, 0, 100, 100);
 
   gfx::Transform negative_scale;
@@ -2004,7 +2013,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // rect 2 is inside rect 1 initially.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(75, 75, 10, 10);
 
@@ -2131,7 +2140,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // rect 2 is inside rect 1 initially.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(10, 10, 1, 1);
 
@@ -2204,7 +2213,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(25, 25, 10, 10);
 
@@ -2268,7 +2277,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(25, 25, 10, 10);
 
@@ -2333,7 +2342,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(0, 0, 200, 100);
 
@@ -2387,7 +2396,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // rect 2 and 3 are outside rect 1 initially.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(120, 120, 10, 10);
   gfx::Rect rect3(100, 100, 100, 20);
@@ -2506,7 +2515,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // rect 3 is inside of combined rect of rect 1 and rect 2.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(100, 0, 60, 60);
   gfx::Rect rect3(10, 10, 120, 30);
@@ -2630,10 +2639,12 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = CompositorFrameBuilder()
-                              .AddDefaultRenderPass()
-                              .AddDefaultRenderPass()
-                              .Build();
+  CompositorFrame compositor_frame = CompositorFrameBuilder()
+                                         .AddDefaultRenderPass()
+                                         .AddDefaultRenderPass()
+                                         .Build();
+  AggregatedFrame frame;
+  frame.render_pass_list = std::move(compositor_frame.render_pass_list);
 
   // rect 3 is inside of combined rect of rect 1 and rect 2.
   // rect 4 is identical to rect 3, but in a separate render pass.
@@ -2682,7 +2693,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // rect 3 is inside of combined rect of rect 1 and rect 2.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(100, 0, 60, 60);
 
@@ -2755,7 +2766,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // rect 3 is inside of combined rect of rect 1 and rect 2.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
 
   std::unique_ptr<RenderPass> render_pass2 = RenderPass::Create();
@@ -2822,7 +2833,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(50, 50, 25, 25);
   gfx::Rect clip_rect(0, 0, 60, 60);
@@ -2937,7 +2948,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(50, 50, 25, 25);
 
@@ -2983,7 +2994,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(50, 0, 100, 100);
   gfx::Rect rect3(0, 0, 25, 25);
@@ -3161,7 +3172,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect1_1(0, 0, 50, 50);
   gfx::Rect rect1_2(50, 0, 50, 50);
@@ -3336,7 +3347,7 @@
 
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect rect1(0, 0, 100, 100);
   gfx::Rect rect2(10, 10, 50, 50);
   gfx::Rect rect3(0, 0, 10, 10);
@@ -3439,7 +3450,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   // The size of this DrawQuad will be 237790x237790 > 2^32 (uint32_t.max())
   // which caused the integer overflow in the bug.
   gfx::Rect rect1(237790, 237790);
@@ -3949,7 +3960,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
 
   // The quad with rounded corner does not completely cover the quad below it.
   // The corners of the below quad are visiblg through the clipped corners.
@@ -4006,7 +4017,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // The quad with rounded corner completely covers the quad below it.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
   gfx::Rect quad_rect(10, 10, 1000, 1000);
   gfx::RRectF rounded_corner_bounds(gfx::RectF(quad_rect), 10.f);
   gfx::Rect occluded_quad_rect(13, 13, 994, 994);
@@ -4061,7 +4072,7 @@
 
   // The two partially occluded quads will be split into two additional quads,
   // preserving only the visible regions.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
 
   //  +--------------------------------+
   //  |***+----------------------+ <- Large occluding Rect
@@ -4154,7 +4165,7 @@
   StubDisplayClient client;
   display_->Initialize(&client, manager_.surface_manager());
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
 
   const bool is_clipped = false;
   const bool are_contents_opaque = true;
@@ -4270,7 +4281,7 @@
       1.5f);
   display_->Resize(gfx::Size(1000, 1000));
 
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
 
   const bool is_clipped = false;
   const bool are_contents_opaque = true;
@@ -4315,7 +4326,7 @@
   display_->Initialize(&client, manager_.surface_manager());
 
   // The quad with rounded corner completely covers the quad below it.
-  CompositorFrame frame = MakeDefaultCompositorFrame();
+  AggregatedFrame frame = MakeDefaultAggregatedFrame();
 
   //      +----------------------+
   //      |                      | <- Large occluding Rect
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 153162e..a2452e8 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -425,9 +425,9 @@
   sk_sp<SkColorFilter> color_filter = nullptr;
   // Root of the calculated backdrop filter DAG to be applied to the render pass
   sk_sp<SkImageFilter> backdrop_filter = nullptr;
-  // Resolved mask image and calculated transform matrix
-  sk_sp<SkImage> mask_image = nullptr;
-  SkMatrix mask_to_quad_matrix;
+  // Resolved mask image and calculated transform matrix baked into an SkShader,
+  // which will be applied using SkCanvas::clipShader in RPDQ's coord space.
+  sk_sp<SkShader> mask_shader = nullptr;
   // Backdrop border box for the render pass, to clip backdrop-filtered content
   base::Optional<gfx::RRectF> backdrop_filter_bounds;
   // The content space bounds that includes any filtered extents. If empty,
@@ -540,14 +540,11 @@
 
 enum class SkiaRenderer::BypassMode {
   // The RenderPass's contents' blendmode would have made a transparent black
-  // image
-  // and the RenderPass's own blend mode has no effect on transparent black.
+  // image and the RenderPass's own blend mode does not effect transparent black
   kSkip,
   // The renderPass's contents' creates a transparent image, but the
-  // RenderPass's
-  // own blend mode must still process the transparent pixels (e.g. certain
-  // filters
-  // affect transparent black).
+  // RenderPass's own blend mode must still process the transparent pixels (e.g.
+  // certain filters affect transparent black).
   kDrawTransparentQuad,
   // Can draw the bypass quad with the modified parameters
   kDrawBypassQuad
@@ -1145,20 +1142,6 @@
     }
   }
 
-  if (rpdq_params.mask_image.get()) {
-    // The old behavior (in skia) was to filter the clipmask based on the
-    // setting in the layer's paint. Now we can set that to whatever we want
-    // when we make the clip-shader. For now, I will replicate the old (impl)
-    // logic.
-    SkFilterQuality filtering =
-        layer_paint.getFilterQuality() == kNone_SkFilterQuality
-            ? kNone_SkFilterQuality
-            : kLow_SkFilterQuality;
-    current_canvas_->save();
-    current_canvas_->clipShader(rpdq_params.mask_image->makeShader(
-        SkTileMode::kClamp, SkTileMode::kClamp,
-        &rpdq_params.mask_to_quad_matrix, filtering));
-  }
   SkRect bounds = gfx::RectFToSkRect(rpdq_params.bypass_clip.has_value()
                                          ? *rpdq_params.bypass_clip
                                          : params->visible_rect);
@@ -1196,16 +1179,21 @@
   // the canvas. But there are several requirements in order for the order of
   // operations to be consistent with what RenderPasses require:
   // 1. Backdrop filtering always requires a layer.
-  // 2. A complex image filter needs a layer if there is a mask, since Skia
-  // applies the mask filter before the paint's image filter.
-  // 3. The content bypassing the renderpass needs to be clipped before the
+  // 2. The content bypassing the renderpass needs to be clipped before the
   //    image filter is evaluated.
   bool needs_bypass_clip = rpdq_params.needs_bypass_clip(params->visible_rect);
   bool needs_save_layer = false;
   if (rpdq_params.backdrop_filter)
     needs_save_layer = true;
   else if (rpdq_params.has_complex_image_filter())
-    needs_save_layer = rpdq_params.mask_image || needs_bypass_clip;
+    needs_save_layer = needs_bypass_clip;
+
+  if (rpdq_params.mask_shader) {
+    // Apply the mask image using clipShader(), this works the same regardless
+    // of if we need a saveLayer for image filtering since the clip is applied
+    // at the end automatically.
+    current_canvas_->clipShader(rpdq_params.mask_shader);
+  }
 
   if (needs_save_layer) {
     PrepareCanvasForRPDQ(rpdq_params, params);
@@ -1213,12 +1201,10 @@
     paint->setAlphaf(params->opacity);
     paint->setBlendMode(params->blend_mode);
   } else {
-    // At this point, the image filter and/or color filter can be set on the
-    // paint. If there is a mask image, it can be converted to a mask shader.
+    // At this point, the image filter and/or color filter are on the paint.
     DCHECK(!rpdq_params.backdrop_filter);
     if (rpdq_params.color_filter) {
-      // Use the color filter directly, instead of the image filter; since color
-      // filters are applied before masks, this could be combined with a mask
+      // Use the color filter directly, instead of the image filter.
       if (paint->getColorFilter()) {
         paint->setColorFilter(
             rpdq_params.color_filter->makeComposed(paint->refColorFilter()));
@@ -1227,9 +1213,7 @@
       }
       DCHECK(paint->getColorFilter());
     } else if (rpdq_params.image_filter) {
-      // Store the image filter on the paint, but since this effect is applied
-      // last it's not compatible with masks as a shader
-      DCHECK(!rpdq_params.mask_image);
+      // Store the image filter on the paint.
       if (params->opacity != 1.f) {
         // Apply opacity as the last step of image filter so it is uniform
         // across any overlapping content produced by the image filters.
@@ -1242,29 +1226,6 @@
         paint->setImageFilter(rpdq_params.image_filter);
       }
     }
-
-    // This is not an else-if since the color filter image filter can be
-    // combined with the mask filter correctly.
-    if (rpdq_params.mask_image) {
-      // The mask shader is evaluated in the bypass'ed quad's local coordinate
-      // space, so must update the shader matrix to still sample the image in
-      // the RP coordinate space.
-      SkMatrix local_matrix = SkMatrix::I();
-      if (rpdq_params.bypass_transform.has_value()) {
-        bool inverted = rpdq_params.bypass_transform->invert(&local_matrix);
-        // Invertibility was a requirement for being bypassable.
-        DCHECK(inverted);
-      }
-      local_matrix.preConcat(rpdq_params.mask_to_quad_matrix);
-
-      auto mask_filter = SkShaderMaskFilter::Make(
-          rpdq_params.mask_image->makeShader(&local_matrix));
-      // Confirm that the paint didn't already have a mask filter, and that it's
-      // captured properly afterwards on the paint.
-      DCHECK(!paint->getMaskFilter());
-      paint->setMaskFilter(std::move(mask_filter));
-      DCHECK(paint->getMaskFilter());
-    }
   }
 
   // Whether or not we saved a layer, clip the bypassed RenderPass's content
@@ -1281,8 +1242,12 @@
   // When the draw call only takes a color and not an SkPaint, rpdq params
   // with just a color filter can be handled directly. Otherwise, the rpdq
   // params must use a layer on the canvas.
-  bool needs_save_layer = rpdq_params.has_complex_image_filter() ||
-                          rpdq_params.backdrop_filter || rpdq_params.mask_image;
+  bool needs_save_layer =
+      rpdq_params.has_complex_image_filter() || rpdq_params.backdrop_filter;
+  if (rpdq_params.mask_shader) {
+    current_canvas_->clipShader(rpdq_params.mask_shader);
+  }
+
   if (needs_save_layer) {
     PrepareCanvasForRPDQ(rpdq_params, params);
   } else if (rpdq_params.color_filter) {
@@ -2326,15 +2291,17 @@
   const SkImage* mask_image = mask_image_builder.sk_image();
   DCHECK_EQ(!!mask_resource_id, !!mask_image);
   if (mask_image) {
-    rpdq_params.mask_image = sk_ref_sp(mask_image);
-
     // Scale normalized uv rect into absolute texel coordinates.
     SkRect mask_rect = gfx::RectFToSkRect(
         gfx::ScaleRect(quad->mask_uv_rect, quad->mask_texture_size.width(),
                        quad->mask_texture_size.height()));
     // Map to full quad rect so that mask coordinates don't change with clipping
-    rpdq_params.mask_to_quad_matrix = SkMatrix::MakeRectToRect(
+    SkMatrix mask_to_quad_matrix = SkMatrix::MakeRectToRect(
         mask_rect, gfx::RectToSkRect(quad->rect), SkMatrix::kFill_ScaleToFit);
+
+    rpdq_params.mask_shader =
+        mask_image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
+                               &mask_to_quad_matrix, kLow_SkFilterQuality);
   }
 
   const cc::FilterOperations* filters = FiltersForPass(quad->render_pass_id);
@@ -2515,7 +2482,7 @@
   // When the RPDQ was needed because of a copy request, it may not require any
   // advanced filtering/effects at which point it's basically a tiled quad.
   if (!rpdq_params.image_filter && !rpdq_params.backdrop_filter &&
-      !rpdq_params.mask_image) {
+      !rpdq_params.mask_shader) {
     DCHECK(!MustFlushBatchedQuads(quad, nullptr, *params));
     AddQuadToBatch(content_image.get(), valid_texel_bounds, params);
     return;
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index e15f6bd..e33b0d3 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -28,6 +28,7 @@
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/surfaces/surface_range.h"
 #include "components/viz/service/display/display_resource_provider.h"
 #include "components/viz/service/display/renderer_utils.h"
@@ -1629,7 +1630,7 @@
   return true;
 }
 
-CompositorFrame SurfaceAggregator::Aggregate(
+AggregatedFrame SurfaceAggregator::Aggregate(
     const SurfaceId& surface_id,
     base::TimeTicks expected_display_time,
     gfx::OverlayTransform display_transform,
@@ -1660,9 +1661,8 @@
       TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
       "SurfaceAggregation", "display_trace", display_trace_id_);
 
-  CompositorFrame frame;
-  frame.metadata.display_transform_hint = display_transform;
-  frame.metadata.top_controls_visible_height =
+  AggregatedFrame frame;
+  frame.top_controls_visible_height =
       root_surface_frame.metadata.top_controls_visible_height;
 
   dest_pass_list_ = &frame.render_pass_list;
@@ -1696,8 +1696,9 @@
 
   PropagateCopyRequestPasses();
   has_copy_requests_ = !copy_request_passes_.empty();
-  frame.metadata.may_contain_video = prewalk_result.may_contain_video;
-  frame.metadata.content_color_usage = prewalk_result.content_color_usage;
+  frame.has_copy_requests = has_copy_requests_;
+  frame.may_contain_video = prewalk_result.may_contain_video;
+  frame.content_color_usage = prewalk_result.content_color_usage;
 
   CopyUndrawnSurfaces(&prewalk_result);
   referenced_surfaces_.insert(surface_id);
@@ -1743,15 +1744,15 @@
     Surface* surface = manager_->GetSurfaceForId(it.first);
     if (surface) {
       surface->allocation_group()->TakeAggregatedLatencyInfoUpTo(
-          surface, &frame.metadata.latency_info);
+          surface, &frame.latency_info);
     }
-    if (!ui::LatencyInfo::Verify(frame.metadata.latency_info,
+    if (!ui::LatencyInfo::Verify(frame.latency_info,
                                  "SurfaceAggregator::Aggregate")) {
       break;
     }
   }
 
-  frame.metadata.delegated_ink_metadata = std::move(delegated_ink_metadata_);
+  frame.delegated_ink_metadata = std::move(delegated_ink_metadata_);
 
   if (frame_annotator_)
     frame_annotator_->AnnotateAggregatedFrame(&frame);
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 1570461..e4f2435 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -27,6 +27,7 @@
 #include "ui/gfx/overlay_transform.h"
 
 namespace viz {
+class AggregatedFrame;
 class CompositorFrame;
 class DisplayResourceProvider;
 class Surface;
@@ -45,7 +46,7 @@
    public:
     virtual ~FrameAnnotator() = default;
 
-    virtual void AnnotateAggregatedFrame(CompositorFrame* frame) = 0;
+    virtual void AnnotateAggregatedFrame(AggregatedFrame* frame) = 0;
   };
 
   SurfaceAggregator(SurfaceManager* manager,
@@ -58,7 +59,7 @@
   // been invalidated. It can be used in cases where we still want to support
   // partial damage but the target surface might need contents outside the
   // damage rect of the root surface.
-  CompositorFrame Aggregate(const SurfaceId& surface_id,
+  AggregatedFrame Aggregate(const SurfaceId& surface_id,
                             base::TimeTicks expected_display_time,
                             gfx::OverlayTransform display_transform,
                             const gfx::Rect& target_damage = gfx::Rect(),
diff --git a/components/viz/service/display/surface_aggregator_perftest.cc b/components/viz/service/display/surface_aggregator_perftest.cc
index 1f6fc02..0e20859 100644
--- a/components/viz/service/display/surface_aggregator_perftest.cc
+++ b/components/viz/service/display/surface_aggregator_perftest.cc
@@ -8,6 +8,7 @@
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/service/display/display_resource_provider.h"
 #include "components/viz/service/display/surface_aggregator.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
@@ -149,7 +150,7 @@
       root_support->SubmitCompositorFrame(
           LocalSurfaceId(num_surfaces + 1, root_token), std::move(frame));
 
-      CompositorFrame aggregated = aggregator_->Aggregate(
+      auto aggregated = aggregator_->Aggregate(
           SurfaceId(FrameSinkId(1, num_surfaces + 1),
                     LocalSurfaceId(num_surfaces + 1, root_token)),
           next_fake_display_time, gfx::OVERLAY_TRANSFORM_NONE);
diff --git a/components/viz/service/display/surface_aggregator_pixeltest.cc b/components/viz/service/display/surface_aggregator_pixeltest.cc
index 1db4b02c..3730a6a 100644
--- a/components/viz/service/display/surface_aggregator_pixeltest.cc
+++ b/components/viz/service/display/surface_aggregator_pixeltest.cc
@@ -11,6 +11,7 @@
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/service/display/surface_aggregator.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
@@ -122,7 +123,7 @@
 
   SurfaceAggregator aggregator(this->manager_.surface_manager(),
                                this->resource_provider_.get(), true, false);
-  CompositorFrame aggregated_frame = aggregator.Aggregate(
+  auto aggregated_frame = aggregator.Aggregate(
       root_surface_id, this->GetNextDisplayTime(), gfx::OVERLAY_TRANSFORM_NONE);
 
   bool discard_alpha = false;
@@ -202,7 +203,7 @@
 
   SurfaceAggregator aggregator(this->manager_.surface_manager(),
                                this->resource_provider_.get(), true, false);
-  CompositorFrame aggregated_frame = aggregator.Aggregate(
+  auto aggregated_frame = aggregator.Aggregate(
       root_surface_id, this->GetNextDisplayTime(), gfx::OVERLAY_TRANSFORM_NONE);
 
   bool discard_alpha = false;
@@ -340,7 +341,7 @@
 
   SurfaceAggregator aggregator(this->manager_.surface_manager(),
                                this->resource_provider_.get(), true, false);
-  CompositorFrame aggregated_frame = aggregator.Aggregate(
+  auto aggregated_frame = aggregator.Aggregate(
       root_surface_id, this->GetNextDisplayTime(), gfx::OVERLAY_TRANSFORM_NONE);
 
   bool discard_alpha = false;
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 038bcad..4c60ee6 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -29,6 +29,7 @@
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/service/display/display_resource_provider.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
@@ -134,7 +135,7 @@
     testing::Test::TearDown();
   }
 
-  CompositorFrame AggregateFrame(const SurfaceId& surface_id,
+  AggregatedFrame AggregateFrame(const SurfaceId& surface_id,
                                  gfx::Rect target_damage = gfx::Rect()) {
     return aggregator_.Aggregate(
         surface_id, GetNextDisplayTimeAndIncrement(),
@@ -453,7 +454,7 @@
 
   // Verifies that if the |SharedQuadState::quad_layer_rect| can be covered by
   // |DrawQuad::Rect| in the SharedQuadState.
-  void VerifyQuadCoverSQS(CompositorFrame* aggregated_frame) {
+  void VerifyQuadCoverSQS(AggregatedFrame* aggregated_frame) {
     const SharedQuadState* shared_quad_state = nullptr;
     gfx::Rect draw_quad_coverage;
     for (size_t i = 0; i < aggregated_frame->render_pass_list.size(); ++i) {
@@ -477,7 +478,7 @@
                           const std::vector<SurfaceId>& expected_surface_ids) {
     SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                               root_local_surface_id_);
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     TestPassesMatchExpectations(expected_passes,
                                 &aggregated_frame.render_pass_list);
@@ -650,7 +651,7 @@
     SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
                           device_scale_factor);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     auto& render_pass_list = aggregated_frame.render_pass_list;
     EXPECT_EQ(2u, render_pass_list.size());
@@ -673,7 +674,7 @@
     SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
                           device_scale_factor);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     auto& render_pass_list = aggregated_frame.render_pass_list;
     EXPECT_EQ(1u, render_pass_list.size());
@@ -715,7 +716,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   auto& render_pass_list = aggregated_frame.render_pass_list;
   EXPECT_EQ(2u, render_pass_list.size());
@@ -761,8 +762,7 @@
 
   SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
 
-  CompositorFrame aggregated_frame;
-  aggregated_frame = AggregateFrame(surface_id);
+  auto aggregated_frame = AggregateFrame(surface_id);
   auto id0 = aggregated_frame.render_pass_list[0]->id;
   auto id1 = aggregated_frame.render_pass_list[1]->id;
   EXPECT_NE(id1, id0);
@@ -1123,7 +1123,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(SurfaceSize()), next_display_time()));
-  CompositorFrame frame = AggregateFrame(root_surface_id);
+  auto frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
   EXPECT_EQ(1u, frame.render_pass_list.size());
@@ -1193,7 +1193,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(SurfaceSize()), next_display_time()));
-  CompositorFrame frame = AggregateFrame(root_surface_id);
+  auto frame = AggregateFrame(root_surface_id);
 
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
@@ -1264,7 +1264,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(SurfaceSize()), next_display_time()));
-  CompositorFrame frame = AggregateFrame(root_surface_id);
+  auto frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
   EXPECT_EQ(1u, frame.render_pass_list.size());
@@ -1349,7 +1349,7 @@
 
   const SurfaceId mirror_display_surface_id(
       mirror_display_sink->frame_sink_id(), mirror_display_local_surface_id);
-  CompositorFrame frame = AggregateFrame(mirror_display_surface_id);
+  auto frame = AggregateFrame(mirror_display_surface_id);
 
   // The reflected surface should be a separate RenderPass as it's scaled. The
   // root RenderPass should have a single RenderPassDrawQuad.
@@ -1431,7 +1431,7 @@
 
   const SurfaceId mirror_display_surface_id(
       mirror_display_sink->frame_sink_id(), mirror_display_local_surface_id);
-  CompositorFrame frame = AggregateFrame(mirror_display_surface_id);
+  auto frame = AggregateFrame(mirror_display_surface_id);
 
   // The reflected surfaces RenderPass should be merged into the root RenderPass
   // since it's not being scaled.
@@ -1583,7 +1583,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   std::vector<Quad> expected_quads = {
       Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
@@ -1594,6 +1594,7 @@
                                        Pass(expected_quads, SurfaceSize())};
   TestPassesMatchExpectations(expected_passes,
                               &aggregated_frame.render_pass_list);
+  EXPECT_TRUE(aggregated_frame.has_copy_requests);
   ASSERT_EQ(2u, aggregated_frame.render_pass_list.size());
   ASSERT_EQ(1u, aggregated_frame.render_pass_list[0]->copy_requests.size());
   DCHECK_EQ(copy_request_ptr,
@@ -1656,7 +1657,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   std::vector<Quad> expected_quads = {
       Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
@@ -1666,6 +1667,7 @@
                                        Pass(root_quads2, SurfaceSize())};
   TestPassesMatchExpectations(expected_passes,
                               &aggregated_frame.render_pass_list);
+  EXPECT_TRUE(aggregated_frame.has_copy_requests);
   ASSERT_EQ(2u, aggregated_frame.render_pass_list.size());
   ASSERT_EQ(1u, aggregated_frame.render_pass_list[0]->copy_requests.size());
   DCHECK_EQ(copy_request_ptr,
@@ -1768,7 +1770,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // First pass should come from surface that had a copy request but was not
   // referenced directly. The second pass comes from the root surface.
@@ -1778,6 +1780,7 @@
                                        Pass(root_quads, SurfaceSize())};
   TestPassesMatchExpectations(expected_passes,
                               &aggregated_frame.render_pass_list);
+  EXPECT_TRUE(aggregated_frame.has_copy_requests);
   ASSERT_EQ(2u, aggregated_frame.render_pass_list.size());
   ASSERT_EQ(1u, aggregated_frame.render_pass_list[0]->copy_requests.size());
   DCHECK_EQ(copy_request_ptr,
@@ -1841,7 +1844,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -2138,7 +2141,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -2329,7 +2332,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -2519,7 +2522,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -2666,7 +2669,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -3015,7 +3018,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(0, 0, 100, 110), next_display_time()));
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
   ASSERT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -3042,7 +3045,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3085,7 +3088,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(SurfaceSize()), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3099,7 +3102,7 @@
                               root_local_surface_id_);
     EXPECT_CALL(aggregated_damage_callback, OnAggregatedDamage(_, _, _, _))
         .Times(0);
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3114,7 +3117,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(SurfaceSize()), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3200,7 +3203,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(SurfaceSize()), next_display_time()));
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
   ASSERT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -3227,7 +3230,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3312,7 +3315,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(0, 0, 200, 200), next_display_time()));
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
   ASSERT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -3339,7 +3342,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3367,7 +3370,7 @@
   {
     SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                               root_local_surface_id_);
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -3399,7 +3402,7 @@
                                       std::move(root_frame));
   }
   {
-    CompositorFrame aggregated_frame = AggregateFrame(second_root_surface_id);
+    auto aggregated_frame = AggregateFrame(second_root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -3408,7 +3411,7 @@
     EXPECT_EQ(gfx::Rect(1, 2, 3, 4), aggregated_pass_list[0]->damage_rect);
   }
   {
-    CompositorFrame aggregated_frame = AggregateFrame(second_root_surface_id);
+    auto aggregated_frame = AggregateFrame(second_root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -3457,7 +3460,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // |id1| is before the fallback id so it shouldn't damage the display.
   EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3522,7 +3525,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // |id1| is before the fallback id so it shouldn't damage the display.
   EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3572,7 +3575,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // |id1| is inside the range so it should damage the display.
   EXPECT_TRUE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3628,7 +3631,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // |id1| is before the fallback id so it shouldn't damage the display.
   EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3724,7 +3727,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(child_local_surface_id, child_surface_size,
                            gfx::Rect(child_surface_size), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -3765,7 +3768,7 @@
                 OnAggregatedDamage(child_local_surface_id, _, _, _))
         .Times(0);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3801,7 +3804,7 @@
                 OnAggregatedDamage(child_local_surface_id, child_surface_size,
                                    expected_damage_rect, next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3835,7 +3838,7 @@
                 OnAggregatedDamage(child_local_surface_id, child_surface_size,
                                    expected_damage_rect, next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -3965,7 +3968,7 @@
                                    gfx::Rect(second_surface_size),
                                    next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -4018,7 +4021,7 @@
                 OnAggregatedDamage(second_local_surface_id, _, _, _))
         .Times(0);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4057,7 +4060,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(second_local_surface_id, second_surface_size,
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4101,7 +4104,7 @@
                 OnAggregatedDamage(second_local_surface_id, second_surface_size,
                                    expected_damage_rect, next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4215,7 +4218,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(0, 0, 100, 100), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     // After aggregation, there should be two render passes with merging
@@ -4244,7 +4247,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(0, 0, 100, 100), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4277,7 +4280,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4304,7 +4307,7 @@
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(0, 0, 100, 100), next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4400,7 +4403,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(0, 0, 230, 250), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_frame.render_pass_list.size());
@@ -4427,7 +4430,7 @@
         aggregated_damage_callback,
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            gfx::Rect(0, 0, 100, 100), next_display_time()));
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4471,7 +4474,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
+    auto aggregated_frame_2 = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
     const auto* quad_to_test =
@@ -4509,7 +4512,7 @@
     EXPECT_CALL(aggregated_damage_callback,
                 OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                    expected_damage_rect, next_display_time()));
-    CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
+    auto aggregated_frame_2 = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
     //  The unioned damage rect from under |quad_to_test| (10,10 60x80)
@@ -4617,7 +4620,7 @@
         OnAggregatedDamage(child_local_surface_id, child_surface_size,
                            expected_child_damage_rect, next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -4650,7 +4653,7 @@
                 OnAggregatedDamage(child_local_surface_id, _, _, _))
         .Times(0);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4760,7 +4763,7 @@
         OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                            expected_root_damage_rect, next_display_time()));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -4794,7 +4797,7 @@
                 OnAggregatedDamage(child_local_surface_id, _, _, _))
         .Times(0);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(expected_num_passes_after_aggregation,
               aggregated_pass_list.size());
@@ -4886,7 +4889,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -4920,7 +4923,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -4971,7 +4974,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -4991,7 +4994,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     // There were no changes since last aggregation, so output should be empty
@@ -5033,7 +5036,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -5084,7 +5087,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
     ASSERT_EQ(3u, aggregated_pass_list.size());
@@ -5163,7 +5166,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -5245,7 +5248,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -5311,7 +5314,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -5342,7 +5345,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -5379,8 +5382,7 @@
   // root render pass damage.
   {
     gfx::Rect target_damage(0, 0, 1, 1);
-    CompositorFrame aggregated_frame =
-        AggregateFrame(root_surface_id, target_damage);
+    auto aggregated_frame = AggregateFrame(root_surface_id, target_damage);
 
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
     ASSERT_EQ(1u, aggregated_pass_list.size());
@@ -5407,7 +5409,7 @@
     aggregator_->set_output_is_secure(true);
   }
 
-  CompositorFrame AggregateFrame(const SurfaceId& surface_id) {
+  AggregatedFrame AggregateFrame(const SurfaceId& surface_id) {
     return aggregator_->Aggregate(surface_id, GetNextDisplayTimeAndIncrement(),
                                   gfx::OVERLAY_TRANSFORM_NONE);
   }
@@ -5482,7 +5484,7 @@
   SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support.get(),
                                      surface_id);
 
-  CompositorFrame frame = AggregateFrame(surface_id);
+  auto frame = AggregateFrame(surface_id);
 
   // Nothing should be available to be returned yet.
   EXPECT_TRUE(client.returned_resources().empty());
@@ -5517,7 +5519,7 @@
   SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support.get(),
                                      surface_id1);
 
-  CompositorFrame frame = AggregateFrame(surface_id1);
+  auto frame = AggregateFrame(surface_id1);
 
   // Nothing should be available to be returned yet.
   EXPECT_TRUE(client.returned_resources().empty());
@@ -5558,7 +5560,7 @@
                               .Build();
   support->SubmitCompositorFrame(local_surface_id, std::move(frame));
 
-  CompositorFrame returned_frame = AggregateFrame(surface_id);
+  auto returned_frame = AggregateFrame(surface_id);
 
   // Nothing should be available to be returned yet.
   EXPECT_TRUE(client.returned_resources().empty());
@@ -5588,7 +5590,7 @@
   SubmitCompositorFrameWithResources(ids2, true, SurfaceId(), support2.get(),
                                      surface2_id);
 
-  CompositorFrame frame = AggregateFrame(surface1_id);
+  auto frame = AggregateFrame(surface1_id);
 
   SubmitCompositorFrameWithResources({}, true, SurfaceId(), support1.get(),
                                      surface1_id);
@@ -5640,8 +5642,7 @@
   SubmitCompositorFrameWithResources(ids3, true, middle_surface_id,
                                      root_support.get(), root_surface_id);
 
-  CompositorFrame frame;
-  frame = AggregateFrame(root_surface_id);
+  auto frame = AggregateFrame(root_surface_id);
 
   auto* pass_list = &frame.render_pass_list;
   ASSERT_EQ(1u, pass_list->size());
@@ -5674,7 +5675,7 @@
   SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support1.get(),
                                      surface1_id);
 
-  CompositorFrame frame = AggregateFrame(surface1_id);
+  auto frame = AggregateFrame(surface1_id);
 
   auto* render_pass = frame.render_pass_list.back().get();
 
@@ -5770,7 +5771,7 @@
                           device_scale_factor);
     SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(surface_id);
+    auto aggregated_frame = AggregateFrame(surface_id);
 
     EXPECT_EQ(3u, aggregated_frame.render_pass_list.size());
     EXPECT_EQ(gfx::ContentColorUsage::kHDR,
@@ -5797,7 +5798,7 @@
                           device_scale_factor);
     SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(surface_id);
+    auto aggregated_frame = AggregateFrame(surface_id);
 
     EXPECT_EQ(3u, aggregated_frame.render_pass_list.size());
     EXPECT_EQ(gfx::ContentColorUsage::kHDR,
@@ -5838,7 +5839,7 @@
                           device_scale_factor);
     SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(surface_id);
+    auto aggregated_frame = AggregateFrame(surface_id);
 
     EXPECT_EQ(2u, aggregated_frame.render_pass_list.size());
     EXPECT_EQ(gfx::ContentColorUsage::kHDR,
@@ -5859,7 +5860,7 @@
                           device_scale_factor);
     SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(surface_id);
+    auto aggregated_frame = AggregateFrame(surface_id);
 
     EXPECT_EQ(3u, aggregated_frame.render_pass_list.size());
     EXPECT_EQ(gfx::ContentColorUsage::kHDR,
@@ -5918,13 +5919,12 @@
 
         SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                                   root_local_surface_id_);
-        CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+        auto aggregated_frame = AggregateFrame(root_surface_id);
         const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
         // Make sure the root render pass has a color space that matches
         // expected generalization.
-        ASSERT_EQ(aggregated_frame.metadata.content_color_usage,
-                  content_color_usage);
+        ASSERT_EQ(aggregated_frame.content_color_usage, content_color_usage);
         ASSERT_EQ(aggregated_pass_list[0]->content_color_usage,
                   content_color_usage);
       };
@@ -5971,11 +5971,11 @@
 
   // On first frame there is no existing cache texture to worry about re-using,
   // so we don't worry what this bool is set to.
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // No Surface changed, so no damage should be given.
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     EXPECT_FALSE(aggregated_frame.render_pass_list[0]
                      ->has_damage_from_contributing_content);
   }
@@ -5988,7 +5988,7 @@
     child_sink_->SubmitCompositorFrame(child_local_surface_id,
                                        std::move(child_surface_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // True for new child_frame with damage.
     EXPECT_TRUE(aggregated_frame.render_pass_list[0]
                     ->has_damage_from_contributing_content);
@@ -6003,7 +6003,7 @@
     child_sink_->SubmitCompositorFrame(child_local_surface_id,
                                        std::move(child_surface_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // False for new child_frame without damage.
     EXPECT_FALSE(aggregated_frame.render_pass_list[0]
                      ->has_damage_from_contributing_content);
@@ -6051,11 +6051,11 @@
 
   // On first frame there is no existing cache texture to worry about re-using,
   // so we don't worry what this bool is set to.
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // No Surface changed, so no damage should be given.
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     EXPECT_FALSE(aggregated_frame.render_pass_list[0]
                      ->has_damage_from_contributing_content);
   }
@@ -6093,7 +6093,7 @@
     child_sink_->SubmitCompositorFrame(child_local_surface_id,
                                        std::move(child_surface_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // True for new grand_child_frame.
     EXPECT_TRUE(aggregated_frame.render_pass_list[0]
                     ->has_damage_from_contributing_content);
@@ -6101,7 +6101,7 @@
 
   // No Surface changed, so no damage should be given.
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     EXPECT_FALSE(aggregated_frame.render_pass_list[0]
                      ->has_damage_from_contributing_content);
   }
@@ -6114,7 +6114,7 @@
     grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id,
                                                std::move(grand_child_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // True for new grand_child_frame with damage.
     EXPECT_TRUE(aggregated_frame.render_pass_list[0]
                     ->has_damage_from_contributing_content);
@@ -6129,7 +6129,7 @@
     grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id,
                                                std::move(grand_child_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // False for new grand_child_frame without damage.
     EXPECT_FALSE(aggregated_frame.render_pass_list[0]
                      ->has_damage_from_contributing_content);
@@ -6175,7 +6175,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // On first frame there is no existing cache texture to worry about re-using,
   // so we don't worry what this bool is set to.
@@ -6185,7 +6185,7 @@
 
   // No Surface changed, so no damage should be given.
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     EXPECT_FALSE(aggregated_frame.render_pass_list[0]
                      ->has_damage_from_contributing_content);
     EXPECT_FALSE(aggregated_frame.render_pass_list[1]
@@ -6200,7 +6200,7 @@
     child_sink_->SubmitCompositorFrame(child_local_surface_id,
                                        std::move(child_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // True for new child_frame.
     EXPECT_TRUE(aggregated_frame.render_pass_list[0]
                     ->has_damage_from_contributing_content);
@@ -6230,7 +6230,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -6261,7 +6261,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
     // Only the visible area is damaged.
@@ -6288,7 +6288,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
     // Should have full damage.
@@ -6338,7 +6338,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -6369,7 +6369,7 @@
     child_sink_->SubmitCompositorFrame(child_local_surface_id,
                                        std::move(child_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
     // Only the visible area is damaged.
@@ -6396,7 +6396,7 @@
     child_sink_->SubmitCompositorFrame(child_local_surface_id,
                                        std::move(child_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
     // Should have full damage.
@@ -6441,7 +6441,7 @@
   root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                     std::move(root_frame));
   // The damage rect of the very first frame is always the full rect
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // Parameters used for damage rect testing
   gfx::Transform transform(0.5, 0, 0, 0.5, 20, 0);
@@ -6467,7 +6467,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     // The root damage rect should be the size of the child surface damage rect
     gfx::Rect expected_damage_rect(20, 0, 50, 50);
@@ -6494,7 +6494,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     // The root damage rect should be the size of the clipped child surface
     // damage rect
@@ -6555,7 +6555,7 @@
   root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                     std::move(root_frame));
 
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   // Frame # 0 - Full occluding damage rect
   // The damage rect of the very first frame is always the full rect
@@ -6585,7 +6585,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
     // The video quad (10, 0, 80, 80) unions the solid quad on top (60, 0, 40,
@@ -6608,7 +6608,7 @@
                                        std::move(child_surface_frame));
 
     // No change in root frame
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
     // Only the video quad (10, 0, 80, 80) is damaged
@@ -6647,7 +6647,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
     // The video quad (10, 0, 80, 80) unions the expose damage from removing
@@ -6682,7 +6682,7 @@
     root_sink_->SubmitCompositorFrame(root_local_surface_id_,
                                       std::move(root_frame));
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
     // The video quad (10, 0, 80, 80) unions the solid quad on top (60, 0, 40,
@@ -6769,7 +6769,7 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
@@ -6809,7 +6809,7 @@
   }
 
   {
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
 
     ASSERT_EQ(3u, aggregated_pass_list.size());
@@ -6879,7 +6879,7 @@
               OnAggregatedDamage(root_local_surface_id_, surface_size,
                                  gfx::Rect(surface_size), next_display_time()));
 
-  CompositorFrame frame =
+  auto frame =
       aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement(),
                             gfx::OVERLAY_TRANSFORM_ROTATE_90);
   gfx::Rect transformed_rect(surface_size.height(), surface_size.width());
@@ -6938,7 +6938,7 @@
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
 
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   auto* aggregated_first_pass_sqs =
       aggregated_frame.render_pass_list[0]->shared_quad_state_list.front();
 
@@ -7023,7 +7023,7 @@
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
 
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   auto* aggregated_first_pass_sqs =
       aggregated_frame.render_pass_list[1]->shared_quad_state_list.front();
 
@@ -7109,7 +7109,7 @@
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
 
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   auto* aggregated_first_pass_sqs =
       aggregated_frame.render_pass_list[1]->shared_quad_state_list.front();
 
@@ -7172,7 +7172,7 @@
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
 
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   // Only one aggregated quad will result, because the use of
   // is_fast_border_radius will result in the child surface being merged
   // into the parent.
@@ -7253,7 +7253,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(0, 0, 230, 250), next_display_time()));
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
   // For the second aggregation we only damage the child surface at
@@ -7281,7 +7281,7 @@
   EXPECT_CALL(aggregated_damage_callback,
               OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                  expected_damage_rect, next_display_time()));
-  CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
+  auto aggregated_frame_2 = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 }
 
@@ -7357,7 +7357,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(0, 0, 100, 100), next_display_time()));
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 
   // For the second aggregation we only damage the child surface at
@@ -7377,7 +7377,7 @@
   EXPECT_CALL(aggregated_damage_callback,
               OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                                  expected_damage_rect, next_display_time()));
-  CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
+  auto aggregated_frame_2 = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
 }
 
@@ -7431,7 +7431,7 @@
     SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                               root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // Merging allowed, so 1 pass should be present.
     EXPECT_EQ(1u, aggregated_frame.render_pass_list.size());
   }
@@ -7459,7 +7459,7 @@
     SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                               root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
     // Merging not allowed, so 2 passes should be present.
     EXPECT_EQ(2u, aggregated_frame.render_pass_list.size());
   }
@@ -7517,7 +7517,7 @@
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
 
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   // Merging not allowed, but child rect should be dropped.
   EXPECT_EQ(1u, aggregated_frame.render_pass_list.size());
 }
@@ -7573,7 +7573,7 @@
     SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                               root_local_surface_id_);
 
-    CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+    auto aggregated_frame = AggregateFrame(root_surface_id);
 
     // Merging not allowed, so 2 passes should be present.
     ASSERT_EQ(2u, aggregated_frame.render_pass_list.size());
@@ -7686,7 +7686,7 @@
       aggregated_damage_callback,
       OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
                          gfx::Rect(0, 0, 100, 100), next_display_time()));
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
   testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
   const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
   EXPECT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -7868,10 +7868,10 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   std::unique_ptr<DelegatedInkMetadata> actual_metadata =
-      std::move(aggregated_frame.metadata.delegated_ink_metadata);
+      std::move(aggregated_frame.delegated_ink_metadata);
   EXPECT_TRUE(actual_metadata);
   ExpectDelegatedInkMetadataIsEqual(*actual_metadata.get(), metadata);
 }
@@ -8006,13 +8006,13 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   metadata = DelegatedInkMetadata(pt, metadata.diameter(), metadata.color(),
                                   metadata.timestamp(), area);
 
   std::unique_ptr<DelegatedInkMetadata> actual_metadata =
-      std::move(aggregated_frame.metadata.delegated_ink_metadata);
+      std::move(aggregated_frame.delegated_ink_metadata);
   EXPECT_TRUE(actual_metadata);
   ExpectDelegatedInkMetadataIsEqual(*actual_metadata.get(), metadata);
 }
@@ -8131,13 +8131,13 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   metadata = DelegatedInkMetadata(pt, metadata.diameter(), metadata.color(),
                                   metadata.timestamp(), area);
 
   std::unique_ptr<DelegatedInkMetadata> actual_metadata =
-      std::move(aggregated_frame.metadata.delegated_ink_metadata);
+      std::move(aggregated_frame.delegated_ink_metadata);
   EXPECT_TRUE(actual_metadata);
   ExpectDelegatedInkMetadataIsEqual(*actual_metadata.get(), metadata);
 }
@@ -8269,14 +8269,14 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
   DelegatedInkMetadata expected_metadata = DelegatedInkMetadata(
       pt, later_metadata.diameter(), later_metadata.color(),
       later_metadata.timestamp(), area);
 
   std::unique_ptr<DelegatedInkMetadata> actual_metadata =
-      std::move(aggregated_frame.metadata.delegated_ink_metadata);
+      std::move(aggregated_frame.delegated_ink_metadata);
   EXPECT_TRUE(actual_metadata);
   ExpectDelegatedInkMetadataIsEqual(*actual_metadata.get(), expected_metadata);
 }
@@ -8332,9 +8332,9 @@
 
   SurfaceId root_surface_id(root_sink_->frame_sink_id(),
                             root_local_surface_id_);
-  CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+  auto aggregated_frame = AggregateFrame(root_surface_id);
 
-  EXPECT_FALSE(aggregated_frame.metadata.delegated_ink_metadata);
+  EXPECT_FALSE(aggregated_frame.delegated_ink_metadata);
 
   // Now add a CopyOutputRequest on the child surface, so that the delegated
   // ink metadata does get populated on the aggregated frame.
@@ -8345,7 +8345,7 @@
   aggregated_frame = AggregateFrame(root_surface_id);
 
   std::unique_ptr<DelegatedInkMetadata> actual_metadata =
-      std::move(aggregated_frame.metadata.delegated_ink_metadata);
+      std::move(aggregated_frame.delegated_ink_metadata);
   EXPECT_TRUE(actual_metadata);
   ExpectDelegatedInkMetadataIsEqual(*actual_metadata.get(), metadata);
 }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 89d252b..3ce75948 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1454,6 +1454,13 @@
   }
 #endif
 
+  context_state_ = dependency_->GetSharedContextState();
+  DCHECK(context_state_);
+  if (!context_state_->gr_context()) {
+    DLOG(ERROR) << "Failed to create GrContext";
+    return false;
+  }
+
   if (is_using_vulkan()) {
     if (!InitializeForVulkan())
       return false;
@@ -1472,12 +1479,6 @@
 }
 
 bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() {
-  context_state_ = dependency_->GetSharedContextState();
-  if (!context_state_) {
-    DLOG(ERROR) << "Failed to create GrContext";
-    return false;
-  }
-
   auto* context = context_state_->real_context();
   auto* current_gl = context->GetCurrentGL();
   api_ = current_gl->Api;
@@ -1547,8 +1548,6 @@
 }
 
 bool SkiaOutputSurfaceImplOnGpu::InitializeForVulkan() {
-  context_state_ = dependency_->GetSharedContextState();
-  DCHECK(context_state_);
 #if BUILDFLAG(ENABLE_VULKAN)
   if (dependency_->IsOffscreen()) {
     output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
@@ -1610,8 +1609,6 @@
 }
 
 bool SkiaOutputSurfaceImplOnGpu::InitializeForDawn() {
-  context_state_ = dependency_->GetSharedContextState();
-  DCHECK(context_state_);
 #if BUILDFLAG(SKIA_USE_DAWN)
   if (dependency_->IsOffscreen()) {
     output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index bb23f23c..7e10b2b 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -38,7 +38,8 @@
   kSendBlockedEmbedded = 5,
   kThrottleUndrawnFrames = 6,
   kSendDefault = 7,
-  kMaxValue = kSendDefault
+  kThrottleAsRequested = 8,
+  kMaxValue = kThrottleAsRequested
 };
 
 void RecordShouldSendBeginFrame(SendBeginFrameResult result) {
@@ -144,6 +145,10 @@
   UpdateNeedsBeginFramesInternal();
 }
 
+void CompositorFrameSinkSupport::ThrottleBeginFrame(base::TimeDelta interval) {
+  begin_frame_interval_ = interval;
+}
+
 void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
   DCHECK(surface);
   DCHECK(surface->HasActiveFrame());
@@ -833,9 +838,21 @@
 
 bool CompositorFrameSinkSupport::ShouldSendBeginFrame(
     base::TimeTicks frame_time) {
+  // We should throttle OnBeginFrame() if it has been less than
+  // |begin_frame_interval_| since the last one was sent because clients have
+  // requested to update at such rate.
+  const bool should_throttle_as_requested =
+      begin_frame_interval_ > base::TimeDelta() &&
+      (frame_time - last_frame_time_) < begin_frame_interval_;
+  // We might throttle this OnBeginFrame() if it's been less than a second since
+  // the last one was sent, either because clients are unresponsive or have
+  // submitted too many undrawn frames.
+  const bool can_throttle_if_unresponsive_or_excessive =
+      frame_time - last_frame_time_ < base::TimeDelta::FromSeconds(1);
+
   // If there are pending timing details from the previous frame(s),
   // then the client needs to receive the begin-frame.
-  if (!frame_timing_details_.empty()) {
+  if (!frame_timing_details_.empty() && !should_throttle_as_requested) {
     RecordShouldSendBeginFrame(SendBeginFrameResult::kSendFrameTiming);
     return true;
   }
@@ -851,13 +868,9 @@
     return false;
   }
 
-  // We might throttle this OnBeginFrame() if it's been less than a second since
-  // the last one was sent.
-  bool can_throttle =
-      (frame_time - last_frame_time_) < base::TimeDelta::FromSeconds(1);
-
   // Throttle clients that are unresponsive.
-  if (can_throttle && begin_frame_tracker_.ShouldThrottleBeginFrame()) {
+  if (can_throttle_if_unresponsive_or_excessive &&
+      begin_frame_tracker_.ShouldThrottleBeginFrame()) {
     RecordShouldSendBeginFrame(
         SendBeginFrameResult::kThrottleUnresponsiveClient);
     return false;
@@ -875,6 +888,11 @@
     return true;
   }
 
+  if (should_throttle_as_requested) {
+    RecordShouldSendBeginFrame(SendBeginFrameResult::kThrottleAsRequested);
+    return false;
+  }
+
   Surface* surface =
       surface_manager_->GetSurfaceForId(last_activated_surface_id_);
 
@@ -890,7 +908,8 @@
 
   // Throttle clients that have submitted too many undrawn frames.
   uint64_t num_undrawn_frames = active_frame_index - last_drawn_frame_index_;
-  if (can_throttle && num_undrawn_frames > kUndrawnFrameLimit) {
+  if (can_throttle_if_unresponsive_or_excessive &&
+      num_undrawn_frames > kUndrawnFrameLimit) {
     RecordShouldSendBeginFrame(SendBeginFrameResult::kThrottleUndrawnFrames);
     return false;
   }
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index fe2449d8b..3a5f1fa 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -111,6 +111,9 @@
   base::TimeDelta GetPreferredFrameInterval(
       mojom::CompositorFrameSinkType* type) const;
   void InitializeCompositorFrameSinkType(mojom::CompositorFrameSinkType type);
+  // Throttles the BeginFrames to send at |interval| if |interval| is greater
+  // than zero, or clears previously set throttle if zero.
+  void ThrottleBeginFrame(base::TimeDelta interval);
 
   // SurfaceClient implementation.
   void OnSurfaceActivated(Surface* surface) override;
@@ -341,6 +344,11 @@
                 "|last_drawn_frame_index| relies on kFrameIndexStart > 1");
   uint64_t last_drawn_frame_index_ = kFrameIndexStart - 1;
 
+  // This value represents throttling on sending a BeginFrame. If non-zero, it
+  // represents the duration of time in between sending two consecutive frames.
+  // If zero, no throttling would be applied.
+  base::TimeDelta begin_frame_interval_;
+
   // The set of surfaces owned by this frame sink that have pending frame.
   base::flat_set<Surface*> pending_surfaces_;
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index dacc55a..4b39b20 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -1455,4 +1455,54 @@
 
   support->SetNeedsBeginFrame(false);
 }
+
+// Verifies that when CompositorFrameSinkSupport has its |begin_frame_interval_|
+// set, any BeginFrame would be sent only after this interval has passed from
+// the time when the last BeginFrame was sent.
+TEST_F(CompositorFrameSinkSupportTest, BeginFrameInterval) {
+  FakeExternalBeginFrameSource begin_frame_source(0.f, false);
+
+  testing::NiceMock<MockCompositorFrameSinkClient> mock_client;
+  auto support = std::make_unique<CompositorFrameSinkSupport>(
+      &mock_client, &manager_, kAnotherArbitraryFrameSinkId, /*is_root=*/true);
+  SurfaceId id(kAnotherArbitraryFrameSinkId, local_surface_id_);
+  support->SetBeginFrameSource(&begin_frame_source);
+  support->SetNeedsBeginFrame(true);
+  constexpr uint8_t fps = 5;
+  constexpr base::TimeDelta throttled_interval =
+      base::TimeDelta::FromSeconds(1) / fps;
+  support->ThrottleBeginFrame(throttled_interval);
+
+  constexpr base::TimeDelta interval = BeginFrameArgs::DefaultInterval();
+  base::TimeTicks frame_time;
+  uint64_t sequence_number = 1;
+  int sent_frames = 0;
+  BeginFrameArgs args;
+
+  const base::TimeTicks end_time = frame_time + base::TimeDelta::FromSeconds(2);
+
+  base::TimeTicks next_expected_begin_frame = frame_time;
+  while (frame_time < end_time) {
+    args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0,
+                                          sequence_number++, frame_time);
+    if (frame_time < next_expected_begin_frame) {
+      EXPECT_CALL(mock_client, OnBeginFrame(args, _)).Times(0);
+    } else {
+      EXPECT_CALL(mock_client, OnBeginFrame(args, _)).WillOnce([&]() {
+        support->SubmitCompositorFrame(local_surface_id_,
+                                       MakeDefaultCompositorFrame());
+        GetSurfaceForId(id)->MarkAsDrawn();
+        ++sent_frames;
+      });
+      next_expected_begin_frame = throttled_interval + frame_time;
+    }
+    begin_frame_source.TestOnBeginFrame(args);
+    testing::Mock::VerifyAndClearExpectations(&mock_client);
+
+    frame_time += interval;
+  }
+  // In total 10 frames should have been sent (5fps x 2 seconds).
+  EXPECT_EQ(sent_frames, 10);
+  support->SetNeedsBeginFrame(false);
+}
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index 0d71e5f..62fee9f 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -626,4 +626,35 @@
   debug_settings_ = debug_settings;
 }
 
+void FrameSinkManagerImpl::UpdateThrottlingRecursively(
+    const FrameSinkId& frame_sink_id,
+    base::TimeDelta interval) {
+  auto it = support_map_.find(frame_sink_id);
+  if (it != support_map_.end()) {
+    it->second->ThrottleBeginFrame(interval);
+  }
+  auto children = GetChildrenByParent(frame_sink_id);
+  for (auto& id : children)
+    UpdateThrottlingRecursively(id, interval);
+}
+
+void FrameSinkManagerImpl::StartThrottling(
+    const std::vector<FrameSinkId>& frame_sink_ids,
+    base::TimeDelta interval) {
+  DCHECK_GT(interval, base::TimeDelta());
+  if (frame_sinks_throttled)
+    EndThrottling();
+
+  frame_sinks_throttled = true;
+  for (auto& frame_sink_id : frame_sink_ids) {
+    UpdateThrottlingRecursively(frame_sink_id, interval);
+  }
+}
+
+void FrameSinkManagerImpl::EndThrottling() {
+  for (auto& support_map_item : support_map_) {
+    support_map_item.second->ThrottleBeginFrame(base::TimeDelta());
+  }
+  frame_sinks_throttled = false;
+}
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index 569133f..9b5c6ae 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -138,6 +138,9 @@
                        EvictBackBufferCallback callback) override;
   void UpdateDebugRendererSettings(
       const DebugRendererSettings& debug_settings) override;
+  void StartThrottling(const std::vector<FrameSinkId>& frame_sink_ids,
+                       base::TimeDelta interval) override;
+  void EndThrottling() override;
 
   // SurfaceObserver implementation.
   void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override;
@@ -278,6 +281,11 @@
   bool ChildContains(const FrameSinkId& child_frame_sink_id,
                      const FrameSinkId& search_frame_sink_id) const;
 
+  // Updates throttling recursively on a frame sink specified by its |id|
+  // and all its descendants to send BeginFrames at |interval|.
+  void UpdateThrottlingRecursively(const FrameSinkId& id,
+                                   base::TimeDelta interval);
+
   // SharedBitmapManager for the viz display service for receiving software
   // resources in CompositorFrameSinks.
   SharedBitmapManager* const shared_bitmap_manager_;
@@ -332,6 +340,9 @@
 
   base::flat_map<uint32_t, base::ScopedClosureRunner> cached_back_buffers_;
 
+  // This tells if any frame sinks are currently throttled.
+  bool frame_sinks_throttled = false;
+
   THREAD_CHECKER(thread_checker_);
 
   // |video_detector_| is instantiated lazily in order to avoid overhead on
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc b/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
index 396981c3..76e78d5 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
@@ -31,6 +31,7 @@
 constexpr FrameSinkId kFrameSinkIdA(2, 1);
 constexpr FrameSinkId kFrameSinkIdB(3, 1);
 constexpr FrameSinkId kFrameSinkIdC(4, 1);
+constexpr FrameSinkId kFrameSinkIdD(5, 1);
 
 // Holds the four interface objects needed to create a RootCompositorFrameSink.
 struct RootCompositorFrameSinkData {
@@ -85,6 +86,11 @@
            base::Contains(manager_.root_sink_map_, frame_sink_id);
   }
 
+  const base::TimeDelta GetCompositorFrameSinkSupportBeginFrameInterval(
+      const FrameSinkId& id) {
+    return manager_.support_map_[id]->begin_frame_interval_;
+  }
+
   // testing::Test implementation.
   void TearDown() override {
     // Make sure that all FrameSinkSourceMappings have been deleted.
@@ -398,6 +404,72 @@
   EXPECT_EQ("", manager_.GetFrameSinkDebugLabel(kFrameSinkIdA));
 }
 
+// Verifies the the begin frames are throttled properly for the requested frame
+// sinks and their children.
+TEST_F(FrameSinkManagerTest, ThrottleBeginFrame) {
+  // root -> A -> B
+  //      -> C -> D
+  auto root = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
+  auto client_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto client_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+  auto client_c = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
+  auto client_d = CreateCompositorFrameSinkSupport(kFrameSinkIdD);
+
+  // Set up the hierarchy.
+  manager_.RegisterFrameSinkHierarchy(root->frame_sink_id(),
+                                      client_a->frame_sink_id());
+  manager_.RegisterFrameSinkHierarchy(client_a->frame_sink_id(),
+                                      client_b->frame_sink_id());
+  manager_.RegisterFrameSinkHierarchy(root->frame_sink_id(),
+                                      client_c->frame_sink_id());
+  manager_.RegisterFrameSinkHierarchy(client_c->frame_sink_id(),
+                                      client_d->frame_sink_id());
+
+  constexpr base::TimeDelta interval = base::TimeDelta::FromSeconds(1) / 20;
+
+  std::vector<FrameSinkId> ids{kFrameSinkIdRoot, kFrameSinkIdA, kFrameSinkIdB,
+                               kFrameSinkIdC, kFrameSinkIdD};
+
+  // By default, a CompositorFrameSinkSupport shouldn't have its
+  // |begin_frame_interval| set.
+  for (auto& id : ids) {
+    EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
+              base::TimeDelta());
+  }
+
+  manager_.StartThrottling({kFrameSinkIdRoot}, interval);
+  for (auto& id : ids) {
+    EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id), interval);
+  }
+
+  manager_.EndThrottling();
+  for (auto& id : ids) {
+    EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
+              base::TimeDelta());
+  }
+
+  manager_.StartThrottling({kFrameSinkIdB, kFrameSinkIdC}, interval);
+  ids = {kFrameSinkIdB, kFrameSinkIdC, kFrameSinkIdD};
+  for (auto& id : ids) {
+    EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id), interval);
+  }
+
+  manager_.EndThrottling();
+  for (auto& id : ids) {
+    EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
+              base::TimeDelta());
+  }
+
+  manager_.UnregisterFrameSinkHierarchy(root->frame_sink_id(),
+                                        client_a->frame_sink_id());
+  manager_.UnregisterFrameSinkHierarchy(client_a->frame_sink_id(),
+                                        client_b->frame_sink_id());
+  manager_.UnregisterFrameSinkHierarchy(root->frame_sink_id(),
+                                        client_c->frame_sink_id());
+  manager_.UnregisterFrameSinkHierarchy(client_c->frame_sink_id(),
+                                        client_d->frame_sink_id());
+}
+
 namespace {
 
 enum RegisterOrder { REGISTER_HIERARCHY_FIRST, REGISTER_CLIENTS_FIRST };
diff --git a/components/viz/test/compositor_frame_helpers.cc b/components/viz/test/compositor_frame_helpers.cc
index de33c16..f2055c0 100644
--- a/components/viz/test/compositor_frame_helpers.cc
+++ b/components/viz/test/compositor_frame_helpers.cc
@@ -4,6 +4,9 @@
 
 #include "components/viz/test/compositor_frame_helpers.h"
 
+#include <memory>
+#include <utility>
+
 namespace viz {
 namespace {
 
@@ -136,6 +139,13 @@
   return CompositorFrameBuilder().AddDefaultRenderPass().Build();
 }
 
+AggregatedFrame MakeDefaultAggregatedFrame() {
+  AggregatedFrame frame;
+  frame.render_pass_list =
+      std::move(MakeDefaultCompositorFrame().render_pass_list);
+  return frame;
+}
+
 CompositorFrame MakeEmptyCompositorFrame() {
   return CompositorFrameBuilder().Build();
 }
diff --git a/components/viz/test/compositor_frame_helpers.h b/components/viz/test/compositor_frame_helpers.h
index e262f09..872ca876 100644
--- a/components/viz/test/compositor_frame_helpers.h
+++ b/components/viz/test/compositor_frame_helpers.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_VIZ_TEST_COMPOSITOR_FRAME_HELPERS_H_
 #define COMPONENTS_VIZ_TEST_COMPOSITOR_FRAME_HELPERS_H_
 
+#include <memory>
 #include <vector>
 
 #include "base/optional.h"
@@ -12,6 +13,7 @@
 #include "components/viz/common/quads/frame_deadline.h"
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/common/surfaces/aggregated_frame.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "ui/latency/latency_info.h"
 
@@ -73,6 +75,9 @@
 // empty damage_rect. This CompositorFrame is valid and can be sent over IPC.
 CompositorFrame MakeDefaultCompositorFrame();
 
+// Makes an aggregated frame out of the default compositor frame.
+AggregatedFrame MakeDefaultAggregatedFrame();
+
 // Creates a CompositorFrame that will be valid once its render_pass_list is
 // initialized.
 CompositorFrame MakeEmptyCompositorFrame();
diff --git a/components/viz/test/test_frame_sink_manager.h b/components/viz/test/test_frame_sink_manager.h
index b9d3c6d8..ca02f1e 100644
--- a/components/viz/test/test_frame_sink_manager.h
+++ b/components/viz/test/test_frame_sink_manager.h
@@ -62,6 +62,9 @@
                        EvictBackBufferCallback callback) override {}
   void UpdateDebugRendererSettings(
       const DebugRendererSettings& debug_settings) override {}
+  void StartThrottling(const std::vector<FrameSinkId>& frame_sink_ids,
+                       base::TimeDelta interval) override {}
+  void EndThrottling() override {}
 
   mojo::Receiver<mojom::FrameSinkManager> receiver_{this};
   mojo::Remote<mojom::FrameSinkManagerClient> client_;
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index 06347a9..f5b834b 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -173,7 +173,7 @@
 
 bool ProcessLock::IsASiteOrOrigin() const {
   const GURL& lock_url = ProcessLock::lock_url();
-  return lock_url.has_scheme() && lock_url.has_host();
+  return lock_url.has_scheme() && lock_url.has_host() && lock_url.is_valid();
 }
 
 bool ProcessLock::HasOpaqueOrigin() const {
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc
index 4f86577..506852d 100644
--- a/content/browser/portal/portal.cc
+++ b/content/browser/portal/portal.cc
@@ -337,9 +337,10 @@
   DCHECK_EQ(PAGE_TYPE_NORMAL,
             predecessor_controller.GetLastCommittedEntry()->GetPageType());
 
-  // If the portal is showing an error page, reject activation.
-  if (portal_controller.GetLastCommittedEntry()->GetPageType() !=
-      PAGE_TYPE_NORMAL) {
+  // If the portal is crashed or is showing an error page, reject activation.
+  if (portal_contents_->IsCrashed() ||
+      portal_controller.GetLastCommittedEntry()->GetPageType() !=
+          PAGE_TYPE_NORMAL) {
     std::move(callback).Run(
         blink::mojom::PortalActivateResult::kRejectedDueToErrorInPortal);
     return;
@@ -543,6 +544,10 @@
   outer_contents->GetDelegate()->NavigationStateChanged(source, changed_flags);
 }
 
+bool Portal::ShouldFocusPageAfterCrash() {
+  return false;
+}
+
 void Portal::CanDownload(const GURL& url,
                          const std::string& request_method,
                          base::OnceCallback<void(bool)> callback) {
diff --git a/content/browser/portal/portal.h b/content/browser/portal/portal.h
index ed6a370..5f9615b 100644
--- a/content/browser/portal/portal.h
+++ b/content/browser/portal/portal.h
@@ -105,6 +105,7 @@
   WebContents* GetResponsibleWebContents(WebContents* web_contents) override;
   void NavigationStateChanged(WebContents* source,
                               InvalidateTypes changed_flags) override;
+  bool ShouldFocusPageAfterCrash() override;
   void CanDownload(const GURL& url,
                    const std::string& request_method,
                    base::OnceCallback<void(bool)> callback) override;
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc
index c310e9f..4553332 100644
--- a/content/browser/portal/portal_browsertest.cc
+++ b/content/browser/portal/portal_browsertest.cc
@@ -1894,6 +1894,68 @@
             activated_observer.result());
 }
 
+namespace {
+void CrashContents(WebContentsImpl* contents) {
+#if defined(OS_WIN)
+  // TODO(mcnee): |CrashTab| on windows makes it look like the process
+  // terminated normally. For now we crash it properly here.
+  RenderProcessHost* rph = contents->GetMainFrame()->GetProcess();
+  RenderProcessHostWatcher watcher(
+      rph, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+  EXPECT_TRUE(rph->Shutdown(RESULT_CODE_KILLED));
+  watcher.Wait();
+  EXPECT_FALSE(watcher.did_exit_normally());
+#else
+  CrashTab(contents);
+#endif
+  EXPECT_TRUE(contents->IsCrashed());
+}
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, RejectActivationOfCrashedPages) {
+  GURL main_url(embedded_test_server()->GetURL("portal.test", "/title1.html"));
+  ASSERT_TRUE(NavigateToURL(shell(), main_url));
+  WebContentsImpl* web_contents_impl =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
+
+  GURL portal_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  Portal* portal = CreatePortalToUrl(web_contents_impl, portal_url);
+  WebContentsImpl* portal_contents = portal->GetPortalContents();
+  CrashContents(portal_contents);
+
+  PortalActivatedObserver activated_observer(portal);
+  EXPECT_TRUE(
+      ExecJs(main_frame, "document.querySelector('portal').activate();"));
+  EXPECT_EQ(blink::mojom::PortalActivateResult::kRejectedDueToErrorInPortal,
+            activated_observer.WaitForActivateResult());
+}
+
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, ActivatePreviouslyCrashedPortal) {
+  GURL main_url(embedded_test_server()->GetURL("portal.test", "/title1.html"));
+  ASSERT_TRUE(NavigateToURL(shell(), main_url));
+  WebContentsImpl* web_contents_impl =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
+
+  GURL portal_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  Portal* portal = CreatePortalToUrl(web_contents_impl, portal_url);
+  WebContentsImpl* portal_contents = portal->GetPortalContents();
+  CrashContents(portal_contents);
+
+  TestNavigationObserver navigation_observer(portal_contents);
+  EXPECT_TRUE(ExecJs(
+      main_frame,
+      JsReplace("document.querySelector('portal').src = $1;", portal_url)));
+  navigation_observer.Wait();
+
+  PortalActivatedObserver activated_observer(portal);
+  EXPECT_TRUE(
+      ExecJs(main_frame, "document.querySelector('portal').activate();"));
+  EXPECT_EQ(blink::mojom::PortalActivateResult::kPredecessorWillUnload,
+            activated_observer.WaitForActivateResult());
+}
+
 IN_PROC_BROWSER_TEST_F(PortalBrowserTest, CallCreateProxyAndAttachPortalTwice) {
   EXPECT_TRUE(NavigateToURL(
       shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc
index e78d144d..9e8dd7d 100644
--- a/content/browser/renderer_host/code_cache_host_impl.cc
+++ b/content/browser/renderer_host/code_cache_host_impl.cc
@@ -67,13 +67,11 @@
   if (process_lock.is_empty())
     return GURL::EmptyGURL();
 
-  // Case 2: Don't use invalid lock_url as a key.
-  if (!process_lock.lock_url().is_valid())
-    return base::nullopt;
-
   // Case 2: Don't cache the code corresponding to opaque origins. The same
   // origin checks should always fail for opaque origins but the serialized
   // value of opaque origins does not ensure this.
+  // NOTE: HasOpaqueOrigin() will return true if the ProcessLock lock url is
+  // invalid, leading to a return value of base::nullopt.
   if (process_lock.HasOpaqueOrigin())
     return base::nullopt;
 
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 07431d6..152e3ff 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3160,9 +3160,6 @@
 void RenderProcessHostImpl::NotifyRendererIfLockedToSite() {
   ProcessLock process_lock =
       ChildProcessSecurityPolicyImpl::GetInstance()->GetProcessLock(GetID());
-  if (!process_lock.lock_url().is_valid())
-    return;
-
   if (!process_lock.IsASiteOrOrigin())
     return;
 
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index 497c17ff..5a7ccbd 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -1143,13 +1143,20 @@
 
 // static
 base::Optional<url::Origin> SiteInstanceImpl::GetRequestInitiatorSiteLock(
-    GURL lock_url) {
+    const ProcessLock& lock) {
   // The following schemes are safe for sites that require a process lock:
   // - data: - locking |request_initiator| to an opaque origin
   // - http/https - requiring |request_initiator| to match |site_url| with
   //   DomainIs (i.e. suffix-based) comparison.
-  if (lock_url.SchemeIsHTTPOrHTTPS() || lock_url.SchemeIs(url::kDataScheme))
-    return url::Origin::Create(lock_url);
+  if (lock.matches_scheme(url::kHttpScheme) ||
+      lock.matches_scheme(url::kHttpsScheme) ||
+      lock.matches_scheme(url::kDataScheme)) {
+    url::Origin origin = url::Origin::Create(lock.lock_url());
+    // Only return an opaque origin if it's a data url. If http/https creates an
+    // opaque origin, then the url was invalid to begin with.
+    if (!origin.opaque() || lock.matches_scheme(url::kDataScheme))
+      return origin;
+  }
 
   // Other schemes might not be safe to use as |request_initiator_site_lock|.
   // One example is chrome-guest://...
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index c62fd74..26b9f7d 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -408,15 +408,16 @@
                                 const GURL& site_url,
                                 const bool is_guest);
 
-  // Converts |lock_url| into an origin that can be used as
+  // Converts |lock| into an origin that can be used as
   // |URLLoaderFactoryParams::request_initiator_site_lock|.
   // This means that the returned origin can be safely used in a eTLD+1
   // comparison against |network::ResourceRequest::request_initiator|.
   //
-  // base::nullopt is returned if |lock_url| cannot be used as a
+  // base::nullopt is returned if |lock| cannot be used as a
   // |request_initiator_site_lock| (e.g. in case of site_url =
   // chrome-guest://...).
-  static base::Optional<url::Origin> GetRequestInitiatorSiteLock(GURL lock_url);
+  static base::Optional<url::Origin> GetRequestInitiatorSiteLock(
+      const ProcessLock& lock);
 
   // Return an ID of the next BrowsingInstance to be created.  This ID is
   // guaranteed to be higher than any ID of an existing BrowsingInstance.
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index dcaf6af..bece12fd 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -187,6 +187,81 @@
   url::ScopedSchemeRegistryForTests scoped_registry_;
 };
 
+// Tests that SiteInfo works correct as a key for std::map and std::set.
+TEST_F(SiteInstanceTest, SiteInfoAsContainerKey) {
+  std::map<SiteInfo, int> test_map;
+  std::set<SiteInfo> test_set;
+
+  SiteInfo site_info_1(GURL("https://www.foo.com"), GURL("https://foo.com"));
+  SiteInfo site_info_2(GURL("https://www.foo.com"),
+                       GURL("https://www.foo.com"));
+  SiteInfo site_info_3(GURL("https://www.foo.com"),
+                       GURL("https://sub.foo.com"));
+  SiteInfo site_info_4(GURL("https://www.foo.com"), GURL());
+
+  // Test SiteInfoOperators.
+  // Use EXPECT_TRUE and == below to avoid need to define SiteInfo::operator<<.
+  EXPECT_TRUE(site_info_1 == site_info_1);
+  EXPECT_FALSE(site_info_1 == site_info_2);
+  EXPECT_FALSE(site_info_1 == site_info_3);
+  EXPECT_FALSE(site_info_1 == site_info_4);
+  EXPECT_TRUE(site_info_2 == site_info_2);
+  EXPECT_FALSE(site_info_2 == site_info_3);
+  EXPECT_FALSE(site_info_2 == site_info_4);
+  EXPECT_TRUE(site_info_3 == site_info_3);
+  EXPECT_FALSE(site_info_3 == site_info_4);
+  EXPECT_TRUE(site_info_4 == site_info_4);
+
+  EXPECT_TRUE(site_info_1 < site_info_3);  // 'f' before 's'/
+  EXPECT_TRUE(site_info_3 < site_info_2);  // 's' before 'w'/
+  EXPECT_TRUE(site_info_4 < site_info_1);  // Empty string first.
+
+  // Map tests.
+  test_map[site_info_1] = 1;
+  test_map[site_info_2] = 2;
+  test_map[site_info_4] = 4;
+
+  // Make sure std::map treated the different SiteInfo's as distinct.
+  EXPECT_EQ(3u, test_map.size());
+
+  // Test that std::map::find() looks up the correct key.
+  auto it1 = test_map.find(site_info_1);
+  EXPECT_NE(it1, test_map.end());
+  EXPECT_EQ(1, it1->second);
+
+  auto it2 = test_map.find(site_info_2);
+  EXPECT_NE(it2, test_map.end());
+  EXPECT_EQ(2, it2->second);
+
+  EXPECT_EQ(test_map.end(), test_map.find(site_info_3));
+
+  auto it4 = test_map.find(site_info_4);
+  EXPECT_NE(it4, test_map.end());
+  EXPECT_EQ(4, it4->second);
+
+  // Set tests.
+  test_set.insert(site_info_1);
+  test_set.insert(site_info_2);
+  test_set.insert(site_info_4);
+
+  EXPECT_EQ(3u, test_set.size());
+
+  auto itS1 = test_set.find(site_info_1);
+  auto itS2 = test_set.find(site_info_2);
+  auto itS3 = test_set.find(site_info_3);
+  auto itS4 = test_set.find(site_info_4);
+
+  EXPECT_NE(test_set.end(), itS1);
+  EXPECT_NE(test_set.end(), itS2);
+  EXPECT_EQ(test_set.end(), itS3);
+  EXPECT_NE(test_set.end(), itS4);
+
+  // Use EXPECT_TRUE and == below to avoid need to define SiteInfo::operator<<.
+  EXPECT_TRUE(site_info_1 == *itS1);
+  EXPECT_TRUE(site_info_2 == *itS2);
+  EXPECT_TRUE(site_info_4 == *itS4);
+}
+
 // Test to ensure no memory leaks for SiteInstance objects.
 TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
   TestBrowserContext context;
diff --git a/content/browser/url_loader_factory_params_helper.cc b/content/browser/url_loader_factory_params_helper.cc
index c596b14..833285a 100644
--- a/content/browser/url_loader_factory_params_helper.cc
+++ b/content/browser/url_loader_factory_params_helper.cc
@@ -205,13 +205,10 @@
 URLLoaderFactoryParamsHelper::CreateForRendererProcess(
     RenderProcessHost* process) {
   // Attempt to use the process lock as |request_initiator_site_lock|.
-  base::Optional<url::Origin> request_initiator_site_lock;
   auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
   ProcessLock process_lock = policy->GetProcessLock(process->GetID());
-  if (process_lock.lock_url().is_valid()) {
-    request_initiator_site_lock =
-        SiteInstanceImpl::GetRequestInitiatorSiteLock(process_lock.lock_url());
-  }
+  base::Optional<url::Origin> request_initiator_site_lock =
+      SiteInstanceImpl::GetRequestInitiatorSiteLock(process_lock);
 
   // Since this function is about to get deprecated (crbug.com/1098938), it
   // should be fine to not add support for isolation info thus using an empty
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc
index 06847c9..37c56bf4 100644
--- a/content/browser/webui/shared_resources_data_source.cc
+++ b/content/browser/webui/shared_resources_data_source.cc
@@ -190,6 +190,12 @@
       {IDR_NETWORK_HEALTH_MOJOM_LITE_JS,
        "mojo/chromeos/services/network_health/public/mojom/"
        "network_health.mojom-lite.js"},
+      {IDR_NETWORK_DIAGNOSTICS_MOJOM_HTML,
+       "mojo/chromeos/services/network_health/public/mojom/"
+       "network_diagnostics.mojom.html"},
+      {IDR_NETWORK_DIAGNOSTICS_MOJOM_LITE_JS,
+       "mojo/chromeos/services/network_health/public/mojom/"
+       "network_diagnostics.mojom-lite.js"},
   };
 }
 #endif  // !defined(OS_CHROMEOS)
diff --git a/content/browser/webui/web_ui_navigation_browsertest.cc b/content/browser/webui/web_ui_navigation_browsertest.cc
index a0979a1..6df89eb 100644
--- a/content/browser/webui/web_ui_navigation_browsertest.cc
+++ b/content/browser/webui/web_ui_navigation_browsertest.cc
@@ -656,7 +656,8 @@
   EXPECT_EQ(main_frame_url, webui_rfh->GetLastCommittedURL());
   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
       webui_rfh->GetProcess()->GetID()));
-  EXPECT_TRUE(webui_site_instance->GetSiteInfo().process_lock_url().is_valid());
+  EXPECT_FALSE(
+      webui_site_instance->GetSiteInfo().process_lock_url().is_empty());
   EXPECT_EQ(ChildProcessSecurityPolicyImpl::GetInstance()->GetProcessLock(
                 root->current_frame_host()->GetProcess()->GetID()),
             webui_site_instance->GetProcessLock());
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index d611eeb..1c5ae04 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -1248,19 +1248,6 @@
       TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole,
                                     role);
   }
-
-  // Frames and iframes:
-  // If there are children, the fallback content has been rendered and should
-  // be used instead. For example, the fallback content may be rendered if
-  // there was an error loading an <object>. In that case, only expose the
-  // children. A node should not have both children and a child tree.
-  base::Optional<base::UnguessableToken> child_embedding_token =
-      element.GetEmbeddingToken();
-
-  if (child_embedding_token && !src.ChildCount()) {
-    TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kChildTreeId,
-                                  child_embedding_token->ToString());
-  }
 }
 
 void BlinkAXTreeSource::SerializeHTMLAttributes(WebAXObject src,
diff --git a/content/renderer/media/audio/audio_device_factory.cc b/content/renderer/media/audio/audio_device_factory.cc
index 39b0a2b4..8b210159 100644
--- a/content/renderer/media/audio/audio_device_factory.cc
+++ b/content/renderer/media/audio/audio_device_factory.cc
@@ -56,11 +56,11 @@
 }
 
 scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params,
     base::TimeDelta auth_timeout) {
   auto device = base::MakeRefCounted<media::AudioOutputDevice>(
-      AudioOutputIPCFactory::get()->CreateAudioOutputIPC(render_frame_id),
+      AudioOutputIPCFactory::get()->CreateAudioOutputIPC(frame_token),
       AudioOutputIPCFactory::get()->io_task_runner(), params, auth_timeout);
   device->RequestDeviceAuthorization();
   return device;
@@ -75,14 +75,14 @@
 
 scoped_refptr<media::SwitchableAudioRendererSink> NewMixableSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   RenderThreadImpl* render_thread = RenderThreadImpl::current();
   DCHECK(render_thread) << "RenderThreadImpl is not instantiated, or "
                         << "GetOutputDeviceInfo() is called on a wrong thread ";
   DCHECK(!params.processing_id.has_value());
   return render_thread->GetAudioRendererMixerManager()->CreateInput(
-      render_frame_id, params.session_id, params.device_id,
+      frame_token, params.session_id, params.device_id,
       AudioDeviceFactory::GetSourceLatencyType(source_type));
 }
 
@@ -110,22 +110,22 @@
 
 scoped_refptr<media::AudioRendererSink>
 AudioDeviceFactory::NewAudioRendererMixerSink(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   // AudioRendererMixer sinks are always used asynchronously and thus can
   // operate without a timeout value.
-  return NewFinalAudioRendererSink(render_frame_id, params, base::TimeDelta());
+  return NewFinalAudioRendererSink(frame_token, params, base::TimeDelta());
 }
 
 // static
 scoped_refptr<media::AudioRendererSink>
 AudioDeviceFactory::NewAudioRendererSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   if (factory_) {
     scoped_refptr<media::AudioRendererSink> device =
-        factory_->CreateAudioRendererSink(source_type, render_frame_id, params);
+        factory_->CreateAudioRendererSink(source_type, frame_token, params);
     if (device)
       return device;
   }
@@ -135,11 +135,11 @@
   DCHECK(!(params.processing_id.has_value() && IsMixable(source_type)));
 
   if (IsMixable(source_type))
-    return NewMixableSink(source_type, render_frame_id, params);
+    return NewMixableSink(source_type, frame_token, params);
 
   UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
                         false);
-  return NewFinalAudioRendererSink(render_frame_id, params,
+  return NewFinalAudioRendererSink(frame_token, params,
                                    GetDefaultAuthTimeout());
 }
 
@@ -147,18 +147,18 @@
 scoped_refptr<media::SwitchableAudioRendererSink>
 AudioDeviceFactory::NewSwitchableAudioRendererSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   if (factory_) {
     scoped_refptr<media::SwitchableAudioRendererSink> sink =
-        factory_->CreateSwitchableAudioRendererSink(source_type,
-                                                    render_frame_id, params);
+        factory_->CreateSwitchableAudioRendererSink(source_type, frame_token,
+                                                    params);
     if (sink)
       return sink;
   }
 
   if (IsMixable(source_type))
-    return NewMixableSink(source_type, render_frame_id, params);
+    return NewMixableSink(source_type, frame_token, params);
 
   // AudioOutputDevice is not RestartableAudioRendererSink, so we can't return
   // anything for those who wants to create an unmixable sink.
@@ -169,25 +169,25 @@
 // static
 scoped_refptr<media::AudioCapturerSource>
 AudioDeviceFactory::NewAudioCapturerSource(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSourceParameters& params) {
   if (factory_) {
     // We don't pass on |session_id|, as this branch is only used for tests.
     scoped_refptr<media::AudioCapturerSource> source =
-        factory_->CreateAudioCapturerSource(render_frame_id, params);
+        factory_->CreateAudioCapturerSource(frame_token, params);
     if (source)
       return source;
   }
 
   return base::MakeRefCounted<media::AudioInputDevice>(
-      AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id, params),
+      AudioInputIPCFactory::get()->CreateAudioInputIPC(frame_token, params),
       media::AudioInputDevice::Purpose::kUserInput,
       media::AudioInputDevice::DeadStreamDetection::kEnabled);
 }
 
 // static
 media::OutputDeviceInfo AudioDeviceFactory::GetOutputDeviceInfo(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   DCHECK(RenderThreadImpl::current())
       << "RenderThreadImpl is not instantiated, or "
@@ -204,8 +204,7 @@
       base::BindRepeating(&AudioDeviceFactory::NewAudioRendererSink,
                           blink::WebAudioDeviceSourceType::kNone),
       kDeleteTimeout);
-  return cache->GetSinkInfo(render_frame_id, params.session_id,
-                            params.device_id);
+  return cache->GetSinkInfo(frame_token, params.session_id, params.device_id);
 }
 
 AudioDeviceFactory::AudioDeviceFactory() {
@@ -220,18 +219,18 @@
 // static
 scoped_refptr<media::AudioRendererSink>
 AudioDeviceFactory::NewFinalAudioRendererSink(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params,
     base::TimeDelta auth_timeout) {
   if (factory_) {
     scoped_refptr<media::AudioRendererSink> sink =
-        factory_->CreateFinalAudioRendererSink(render_frame_id, params,
+        factory_->CreateFinalAudioRendererSink(frame_token, params,
                                                auth_timeout);
     if (sink)
       return sink;
   }
 
-  return NewOutputDevice(render_frame_id, params, auth_timeout);
+  return NewOutputDevice(frame_token, params, auth_timeout);
 }
 
 }  // namespace content
diff --git a/content/renderer/media/audio/audio_device_factory.h b/content/renderer/media/audio/audio_device_factory.h
index 20ecbe4..133762d6 100644
--- a/content/renderer/media/audio/audio_device_factory.h
+++ b/content/renderer/media/audio/audio_device_factory.h
@@ -36,13 +36,13 @@
   static media::AudioLatency::LatencyType GetSourceLatencyType(
       blink::WebAudioDeviceSourceType source);
 
-  // Creates a sink for AudioRendererMixer. |render_frame_id| refers to the
+  // Creates a sink for AudioRendererMixer. |frame_token| refers to the
   // RenderFrame containing the entity producing the audio. Note: These sinks do
   // not support the blocking GetOutputDeviceInfo() API and instead clients are
   // required to use the GetOutputDeviceInfoAsync() API. As such they are
   // configured with no authorization timeout value.
   static scoped_refptr<media::AudioRendererSink> NewAudioRendererMixerSink(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params);
 
   // Creates an AudioRendererSink bound to an AudioOutputDevice.
@@ -52,7 +52,7 @@
   // AudioOutputDevice is fixed to be restartable.
   static scoped_refptr<media::AudioRendererSink> NewAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params);
 
   // Creates a SwitchableAudioRendererSink bound to an AudioOutputDevice
@@ -60,20 +60,20 @@
   // the sink goes to AOD directly or can be mixed with other audio before that.
   static scoped_refptr<media::SwitchableAudioRendererSink>
   NewSwitchableAudioRendererSink(blink::WebAudioDeviceSourceType source_type,
-                                 int render_frame_id,
+                                 const base::UnguessableToken& frame_token,
                                  const media::AudioSinkParameters& params);
 
   // A helper to get device info in the absence of AudioOutputDevice.
   // Must be called on renderer thread only.
   static media::OutputDeviceInfo GetOutputDeviceInfo(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params);
 
   // Creates an AudioCapturerSource using the currently registered factory.
-  // |render_frame_id| refers to the RenderFrame containing the entity
+  // |frame_token| refers to the RenderFrame containing the entity
   // consuming the audio.
   static scoped_refptr<media::AudioCapturerSource> NewAudioCapturerSource(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSourceParameters& params);
 
  protected:
@@ -89,23 +89,23 @@
   // output device. |auth_timeout| is the authorization timeout allowed for the
   // underlying AudioOutputDevice instance; a timeout of zero means no timeout.
   virtual scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params,
       base::TimeDelta auth_timeout) = 0;
 
   virtual scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params) = 0;
 
   virtual scoped_refptr<media::SwitchableAudioRendererSink>
   CreateSwitchableAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params) = 0;
 
   virtual scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSourceParameters& params) = 0;
 
  private:
@@ -114,7 +114,7 @@
   static AudioDeviceFactory* factory_;
 
   static scoped_refptr<media::AudioRendererSink> NewFinalAudioRendererSink(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params,
       base::TimeDelta auth_timeout);
 
diff --git a/content/renderer/media/audio/audio_input_ipc_factory.cc b/content/renderer/media/audio/audio_input_ipc_factory.cc
index f5cc6d7f..3886a0cc 100644
--- a/content/renderer/media/audio/audio_input_ipc_factory.cc
+++ b/content/renderer/media/audio/audio_input_ipc_factory.cc
@@ -23,13 +23,14 @@
 namespace {
 
 void CreateMojoAudioInputStreamOnMainThread(
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSourceParameters& source_params,
     mojo::PendingRemote<mojom::RendererAudioInputStreamFactoryClient> client,
     const media::AudioParameters& params,
     bool automatic_gain_control,
     uint32_t total_segments) {
-  RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_id);
+  RenderFrameImpl* frame = RenderFrameImpl::FromWebFrame(
+      blink::WebFrame::FromFrameToken(frame_token));
   if (frame) {
     frame->GetAudioInputStreamFactory()->CreateStream(
         std::move(client), source_params.session_id, params,
@@ -39,7 +40,7 @@
 
 void CreateMojoAudioInputStream(
     scoped_refptr<base::SequencedTaskRunner> main_task_runner,
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSourceParameters& source_params,
     mojo::PendingRemote<mojom::RendererAudioInputStreamFactoryClient> client,
     const media::AudioParameters& params,
@@ -47,29 +48,31 @@
     uint32_t total_segments) {
   main_task_runner->PostTask(
       FROM_HERE,
-      base::BindOnce(&CreateMojoAudioInputStreamOnMainThread, frame_id,
+      base::BindOnce(&CreateMojoAudioInputStreamOnMainThread, frame_token,
                      source_params, std::move(client), params,
                      automatic_gain_control, total_segments));
 }
 
 void AssociateInputAndOutputForAec(
     scoped_refptr<base::SequencedTaskRunner> main_task_runner,
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     const base::UnguessableToken& input_stream_id,
     const std::string& output_device_id) {
   main_task_runner->PostTask(
       FROM_HERE,
       base::BindOnce(
-          [](int frame_id, const base::UnguessableToken& input_stream_id,
+          [](const base::UnguessableToken& frame_token,
+             const base::UnguessableToken& input_stream_id,
              const std::string& output_device_id) {
-            RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_id);
+            RenderFrameImpl* frame = RenderFrameImpl::FromWebFrame(
+                blink::WebFrame::FromFrameToken(frame_token));
             if (frame) {
               frame->GetAudioInputStreamFactory()
                   ->AssociateInputAndOutputForAec(input_stream_id,
                                                   output_device_id);
             }
           },
-          frame_id, input_stream_id, output_device_id));
+          frame_token, input_stream_id, output_device_id));
 }
 }  // namespace
 
@@ -90,15 +93,15 @@
 }
 
 std::unique_ptr<media::AudioInputIPC> AudioInputIPCFactory::CreateAudioInputIPC(
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSourceParameters& source_params) const {
   CHECK(!source_params.session_id.is_empty());
   return std::make_unique<MojoAudioInputIPC>(
       source_params,
       base::BindRepeating(&CreateMojoAudioInputStream, main_task_runner_,
-                          frame_id),
+                          frame_token),
       base::BindRepeating(&AssociateInputAndOutputForAec, main_task_runner_,
-                          frame_id));
+                          frame_token));
 }
 
 }  // namespace content
diff --git a/content/renderer/media/audio/audio_input_ipc_factory.h b/content/renderer/media/audio/audio_input_ipc_factory.h
index 2b5c70f..56d14fa 100644
--- a/content/renderer/media/audio/audio_input_ipc_factory.h
+++ b/content/renderer/media/audio/audio_input_ipc_factory.h
@@ -15,6 +15,7 @@
 namespace base {
 class SequencedTaskRunner;
 class SingleThreadTaskRunner;
+class UnguessableToken;
 }  // namespace base
 
 namespace media {
@@ -43,7 +44,7 @@
 
   // The returned object may only be used on io_task_runner().
   std::unique_ptr<media::AudioInputIPC> CreateAudioInputIPC(
-      int frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSourceParameters& source_params) const;
 
  private:
diff --git a/content/renderer/media/audio/audio_output_ipc_factory.cc b/content/renderer/media/audio/audio_output_ipc_factory.cc
index 072201d..92dd24e 100644
--- a/content/renderer/media/audio/audio_output_ipc_factory.cc
+++ b/content/renderer/media/audio/audio_output_ipc_factory.cc
@@ -31,16 +31,17 @@
 }
 
 std::unique_ptr<media::AudioOutputIPC>
-AudioOutputIPCFactory::CreateAudioOutputIPC(int frame_id) const {
-    // Unretained is safe due to the contract at the top of the header file.
-    return std::make_unique<MojoAudioOutputIPC>(
-        base::BindRepeating(&AudioOutputIPCFactory::GetRemoteFactory,
-                            base::Unretained(this), frame_id),
-        io_task_runner_);
+AudioOutputIPCFactory::CreateAudioOutputIPC(
+    const base::UnguessableToken& frame_token) const {
+  // Unretained is safe due to the contract at the top of the header file.
+  return std::make_unique<MojoAudioOutputIPC>(
+      base::BindRepeating(&AudioOutputIPCFactory::GetRemoteFactory,
+                          base::Unretained(this), frame_token),
+      io_task_runner_);
 }
 
 void AudioOutputIPCFactory::RegisterRemoteFactory(
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     blink::BrowserInterfaceBrokerProxy* interface_broker) {
   mojo::PendingRemote<mojom::RendererAudioOutputStreamFactory> factory_remote;
   interface_broker->GetInterface(
@@ -50,32 +51,34 @@
   io_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(&AudioOutputIPCFactory::RegisterRemoteFactoryOnIOThread,
-                     base::Unretained(this), frame_id,
+                     base::Unretained(this), frame_token,
                      std::move(factory_remote)));
 }
 
-void AudioOutputIPCFactory::MaybeDeregisterRemoteFactory(int frame_id) {
+void AudioOutputIPCFactory::MaybeDeregisterRemoteFactory(
+    const base::UnguessableToken& frame_token) {
   io_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
           &AudioOutputIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread,
-          base::Unretained(this), frame_id));
+          base::Unretained(this), frame_token));
 }
 
 mojom::RendererAudioOutputStreamFactory*
-AudioOutputIPCFactory::GetRemoteFactory(int frame_id) const {
+AudioOutputIPCFactory::GetRemoteFactory(
+    const base::UnguessableToken& frame_token) const {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  auto it = factory_remotes_.find(frame_id);
+  auto it = factory_remotes_.find(frame_token);
   return it == factory_remotes_.end() ? nullptr : it->second.get();
 }
 
 void AudioOutputIPCFactory::RegisterRemoteFactoryOnIOThread(
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     mojo::PendingRemote<mojom::RendererAudioOutputStreamFactory>
         factory_pending_remote) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   std::pair<StreamFactoryMap::iterator, bool> emplace_result =
-      factory_remotes_.emplace(frame_id, std::move(factory_pending_remote));
+      factory_remotes_.emplace(frame_token, std::move(factory_pending_remote));
 
   DCHECK(emplace_result.second) << "Attempt to register a factory for a "
                                    "frame which already has a factory "
@@ -89,17 +92,17 @@
   // cannot trigger after destruction.
   emplaced_factory.set_disconnect_handler(base::BindOnce(
       &AudioOutputIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread,
-      base::Unretained(this), frame_id));
+      base::Unretained(this), frame_token));
 }
 
 void AudioOutputIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread(
-    int frame_id) {
+    const base::UnguessableToken& frame_token) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   // This function can be called both by the frame and the connection error
   // handler of the factory remote. Calling erase multiple times even though
   // there is nothing to erase is safe, so we don't have to handle this in any
   // particular way.
-  factory_remotes_.erase(frame_id);
+  factory_remotes_.erase(frame_token);
 }
 
 }  // namespace content
diff --git a/content/renderer/media/audio/audio_output_ipc_factory.h b/content/renderer/media/audio/audio_output_ipc_factory.h
index b8fca60..b8a5171 100644
--- a/content/renderer/media/audio/audio_output_ipc_factory.h
+++ b/content/renderer/media/audio/audio_output_ipc_factory.h
@@ -52,30 +52,32 @@
   // Enables |this| to create MojoAudioOutputIPCs for the specified frame.
   // Does nothing if not using mojo factories.
   void RegisterRemoteFactory(
-      int frame_id,
+      const base::UnguessableToken& frame_token,
       blink::BrowserInterfaceBrokerProxy* interface_broker);
 
   // Every call to the above method must be matched by a call to this one when
   // the frame is destroyed. Does nothing if not using mojo factories.
-  void MaybeDeregisterRemoteFactory(int frame_id);
+  void MaybeDeregisterRemoteFactory(const base::UnguessableToken& frame_token);
 
   // The returned object may only be used on |io_task_runner()|.
   std::unique_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(
-      int frame_id) const;
+      const base::UnguessableToken& frame_token) const;
 
  private:
   using StreamFactoryMap =
-      base::flat_map<int,
+      base::flat_map<base::UnguessableToken,
                      mojo::Remote<mojom::RendererAudioOutputStreamFactory>>;
 
-  mojom::RendererAudioOutputStreamFactory* GetRemoteFactory(int frame_id) const;
+  mojom::RendererAudioOutputStreamFactory* GetRemoteFactory(
+      const base::UnguessableToken& frame_token) const;
 
   void RegisterRemoteFactoryOnIOThread(
-      int frame_id,
+      const base::UnguessableToken& frame_token,
       mojo::PendingRemote<mojom::RendererAudioOutputStreamFactory>
           factory_pending_remote);
 
-  void MaybeDeregisterRemoteFactoryOnIOThread(int frame_id);
+  void MaybeDeregisterRemoteFactoryOnIOThread(
+      const base::UnguessableToken& frame_token);
 
   // Indicates whether mojo factories are used.
   bool UsingMojoFactories() const;
diff --git a/content/renderer/media/audio/audio_output_ipc_factory_unittest.cc b/content/renderer/media/audio/audio_output_ipc_factory_unittest.cc
index faee41f..03a2e92b 100644
--- a/content/renderer/media/audio/audio_output_ipc_factory_unittest.cc
+++ b/content/renderer/media/audio/audio_output_ipc_factory_unittest.cc
@@ -30,6 +30,13 @@
 
 const int kRenderFrameId = 0;
 
+base::UnguessableToken TokenFromInt(int i) {
+  static base::UnguessableToken base_token = base::UnguessableToken::Create();
+  return base::UnguessableToken::Deserialize(
+      base_token.GetHighForSerialization() + i,
+      base_token.GetLowForSerialization() + i);
+}
+
 std::unique_ptr<base::Thread> MakeIOThread() {
   auto io_thread = std::make_unique<base::Thread>("test IO thread");
   base::Thread::Options thread_options(base::MessagePumpType::IO, 0);
@@ -119,7 +126,8 @@
 
   AudioOutputIPCFactory ipc_factory(io_thread->task_runner());
 
-  ipc_factory.RegisterRemoteFactory(kRenderFrameId, &interface_broker);
+  ipc_factory.RegisterRemoteFactory(TokenFromInt(kRenderFrameId),
+                                    &interface_broker);
 
   // To make sure that the pointer stored in |ipc_factory| is connected to
   // |remote_factory|, and also that it's bound to |io_thread|, we create an
@@ -127,14 +135,15 @@
   // This is supposed to call |remote_factory| on the main thread.
   io_thread->task_runner()->PostTask(
       FROM_HERE,
-      base::BindOnce(&AudioOutputIPCFactoryTest::RequestAuthorizationOnIOThread,
-                     base::Unretained(this),
-                     ipc_factory.CreateAudioOutputIPC(kRenderFrameId)));
+      base::BindOnce(
+          &AudioOutputIPCFactoryTest::RequestAuthorizationOnIOThread,
+          base::Unretained(this),
+          ipc_factory.CreateAudioOutputIPC(TokenFromInt(kRenderFrameId))));
 
   // Wait for call to |remote_factory|:
   run_loop.Run();
 
-  ipc_factory.MaybeDeregisterRemoteFactory(0);
+  ipc_factory.MaybeDeregisterRemoteFactory(TokenFromInt(0));
 
   interface_broker.SetBinderForTesting(
       mojom::RendererAudioOutputStreamFactory::Name_, {});
@@ -166,34 +175,37 @@
   AudioOutputIPCFactory ipc_factory(io_thread->task_runner());
 
   for (size_t i = 0; i < n_factories; i++) {
-    ipc_factory.RegisterRemoteFactory(kRenderFrameId + i, &interface_broker);
+    ipc_factory.RegisterRemoteFactory(TokenFromInt(kRenderFrameId + i),
+                                      &interface_broker);
   }
 
   base::RunLoop run_loop;
   remote_factories[0].SetOnCalledCallback(run_loop.QuitWhenIdleClosure());
   io_thread->task_runner()->PostTask(
       FROM_HERE,
-      base::BindOnce(&AudioOutputIPCFactoryTest::RequestAuthorizationOnIOThread,
-                     base::Unretained(this),
-                     ipc_factory.CreateAudioOutputIPC(kRenderFrameId)));
+      base::BindOnce(
+          &AudioOutputIPCFactoryTest::RequestAuthorizationOnIOThread,
+          base::Unretained(this),
+          ipc_factory.CreateAudioOutputIPC(TokenFromInt(kRenderFrameId))));
   run_loop.Run();
 
   // Do some operation and make sure the internal state isn't messed up:
-  ipc_factory.MaybeDeregisterRemoteFactory(1);
+  ipc_factory.MaybeDeregisterRemoteFactory(TokenFromInt(1));
 
   base::RunLoop run_loop2;
   remote_factories[2].SetOnCalledCallback(run_loop2.QuitWhenIdleClosure());
   io_thread->task_runner()->PostTask(
       FROM_HERE,
-      base::BindOnce(&AudioOutputIPCFactoryTest::RequestAuthorizationOnIOThread,
-                     base::Unretained(this),
-                     ipc_factory.CreateAudioOutputIPC(kRenderFrameId + 2)));
+      base::BindOnce(
+          &AudioOutputIPCFactoryTest::RequestAuthorizationOnIOThread,
+          base::Unretained(this),
+          ipc_factory.CreateAudioOutputIPC(TokenFromInt(kRenderFrameId + 2))));
   run_loop2.Run();
 
   for (size_t i = 0; i < n_factories; i++) {
     if (i == 1)
       continue;
-    ipc_factory.MaybeDeregisterRemoteFactory(i);
+    ipc_factory.MaybeDeregisterRemoteFactory(TokenFromInt(i));
   }
 
   interface_broker.SetBinderForTesting(
@@ -219,8 +231,9 @@
 
   AudioOutputIPCFactory ipc_factory(io_thread->task_runner());
 
-  ipc_factory.RegisterRemoteFactory(kRenderFrameId, &interface_broker);
-  ipc_factory.MaybeDeregisterRemoteFactory(kRenderFrameId);
+  ipc_factory.RegisterRemoteFactory(TokenFromInt(kRenderFrameId),
+                                    &interface_broker);
+  ipc_factory.MaybeDeregisterRemoteFactory(TokenFromInt(kRenderFrameId));
   // That there is no factory remaining at destruction is DCHECKed in the
   // AudioOutputIPCFactory destructor.
 
diff --git a/content/renderer/media/audio/audio_renderer_mixer_manager.cc b/content/renderer/media/audio/audio_renderer_mixer_manager.cc
index f4bb6b1..dabd7f67 100644
--- a/content/renderer/media/audio/audio_renderer_mixer_manager.cc
+++ b/content/renderer/media/audio/audio_renderer_mixer_manager.cc
@@ -124,7 +124,7 @@
 
 scoped_refptr<media::AudioRendererMixerInput>
 AudioRendererMixerManager::CreateInput(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const base::UnguessableToken& session_id,
     const std::string& device_id,
     media::AudioLatency::LatencyType latency) {
@@ -136,11 +136,11 @@
   // NewAudioRenderingMixingStrategy didn't ship, https://crbug.com/870836.
   DCHECK(session_id.is_empty());
   return base::MakeRefCounted<media::AudioRendererMixerInput>(
-      this, source_render_frame_id, device_id, latency);
+      this, source_frame_token, device_id, latency);
 }
 
 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const media::AudioParameters& input_params,
     media::AudioLatency::LatencyType latency,
     const media::OutputDeviceInfo& sink_info,
@@ -149,7 +149,7 @@
   DCHECK(sink->HasOneRef());
   DCHECK_EQ(sink_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK);
 
-  const MixerKey key(source_render_frame_id, input_params, latency,
+  const MixerKey key(source_frame_token, input_params, latency,
                      sink_info.device_id());
   base::AutoLock auto_lock(mixers_lock_);
 
@@ -200,19 +200,19 @@
 }
 
 scoped_refptr<media::AudioRendererSink> AudioRendererMixerManager::GetSink(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const std::string& device_id) {
   return create_sink_cb_.Run(
-      source_render_frame_id,
+      source_frame_token,
       media::AudioSinkParameters(base::UnguessableToken(), device_id));
 }
 
 AudioRendererMixerManager::MixerKey::MixerKey(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const media::AudioParameters& params,
     media::AudioLatency::LatencyType latency,
     const std::string& device_id)
-    : source_render_frame_id(source_render_frame_id),
+    : source_frame_token(source_frame_token),
       params(params),
       latency(latency),
       device_id(device_id) {}
diff --git a/content/renderer/media/audio/audio_renderer_mixer_manager.h b/content/renderer/media/audio/audio_renderer_mixer_manager.h
index 8036390..7aacca2 100644
--- a/content/renderer/media/audio/audio_renderer_mixer_manager.h
+++ b/content/renderer/media/audio/audio_renderer_mixer_manager.h
@@ -48,28 +48,28 @@
 
   // Creates an AudioRendererMixerInput with the proper callbacks necessary to
   // retrieve an AudioRendererMixer instance from AudioRendererMixerManager.
-  // |source_render_frame_id| refers to the RenderFrame containing the entity
+  // |source_frame_token| refers to the RenderFrame containing the entity
   // rendering the audio.  Caller must ensure AudioRendererMixerManager outlives
   // the returned input. |device_id| and |session_id| identify the output
   // device to use. If |device_id| is empty and |session_id| is nonzero,
   // output device associated with the opened input device designated by
   // |session_id| is used. Otherwise, |session_id| is ignored.
   scoped_refptr<media::AudioRendererMixerInput> CreateInput(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const base::UnguessableToken& session_id,
       const std::string& device_id,
       media::AudioLatency::LatencyType latency);
 
   // AudioRendererMixerPool implementation.
   media::AudioRendererMixer* GetMixer(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const media::AudioParameters& input_params,
       media::AudioLatency::LatencyType latency,
       const media::OutputDeviceInfo& sink_info,
       scoped_refptr<media::AudioRendererSink> sink) final;
   void ReturnMixer(media::AudioRendererMixer* mixer) final;
   scoped_refptr<media::AudioRendererSink> GetSink(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const std::string& device_id) final;
 
  protected:
@@ -77,7 +77,7 @@
   // more details on the parameters.
   using CreateSinkCB =
       base::RepeatingCallback<scoped_refptr<media::AudioRendererSink>(
-          int source_render_frame_id,
+          const base::UnguessableToken& source_frame_token,
           const media::AudioSinkParameters& params)>;
 
   explicit AudioRendererMixerManager(CreateSinkCB create_sink_cb);
@@ -88,12 +88,12 @@
   // Define a key so that only those AudioRendererMixerInputs from the same
   // RenderView, AudioParameters and output device can be mixed together.
   struct MixerKey {
-    MixerKey(int source_render_frame_id,
+    MixerKey(const base::UnguessableToken& source_frame_token,
              const media::AudioParameters& params,
              media::AudioLatency::LatencyType latency,
              const std::string& device_id);
     MixerKey(const MixerKey& other);
-    int source_render_frame_id;
+    base::UnguessableToken source_frame_token;
     media::AudioParameters params;
     media::AudioLatency::LatencyType latency;
     std::string device_id;
@@ -103,8 +103,8 @@
   // mixers where only irrelevant keys mismatch.
   struct MixerKeyCompare {
     bool operator()(const MixerKey& a, const MixerKey& b) const {
-      if (a.source_render_frame_id != b.source_render_frame_id)
-        return a.source_render_frame_id < b.source_render_frame_id;
+      if (a.source_frame_token != b.source_frame_token)
+        return a.source_frame_token < b.source_frame_token;
       if (a.params.channels() != b.params.channels())
         return a.params.channels() < b.params.channels();
 
diff --git a/content/renderer/media/audio/audio_renderer_mixer_manager_unittest.cc b/content/renderer/media/audio/audio_renderer_mixer_manager_unittest.cc
index e419f90..816e3fc 100644
--- a/content/renderer/media/audio/audio_renderer_mixer_manager_unittest.cc
+++ b/content/renderer/media/audio/audio_renderer_mixer_manager_unittest.cc
@@ -37,8 +37,9 @@
 const char kMatchedDeviceId[] = "matched-device-id";
 const char kNonexistentDeviceId[] = "nonexistent-device-id";
 
-const int kRenderFrameId = 124;
-const int kAnotherRenderFrameId = 678;
+const base::UnguessableToken kFrameToken = base::UnguessableToken::Create();
+const base::UnguessableToken kAnotherFrameToken =
+    base::UnguessableToken::Create();
 }  // namespace
 
 using media::AudioLatency;
@@ -74,19 +75,20 @@
   }
 
   enum class SinkUseState { kExistingSink, kNewSink };
-  media::AudioRendererMixer* GetMixer(int source_render_frame_id,
-                                      const media::AudioParameters& params,
-                                      AudioLatency::LatencyType latency,
-                                      const std::string& device_id,
-                                      SinkUseState sink_state) {
+  media::AudioRendererMixer* GetMixer(
+      const base::UnguessableToken& source_frame_token,
+      const media::AudioParameters& params,
+      AudioLatency::LatencyType latency,
+      const std::string& device_id,
+      SinkUseState sink_state) {
     auto sink = GetSink(
-        source_render_frame_id,
+        source_frame_token,
         media::AudioSinkParameters(base::UnguessableToken(), device_id));
     auto device_info = sink->GetOutputDeviceInfo();
     if (sink_state == SinkUseState::kNewSink)
       EXPECT_CALL(*sink, Start()).Times(1);
-    return manager_->GetMixer(source_render_frame_id, params, latency,
-                              device_info, std::move(sink));
+    return manager_->GetMixer(source_frame_token, params, latency, device_info,
+                              std::move(sink));
   }
 
   void ReturnMixer(media::AudioRendererMixer* mixer) {
@@ -94,13 +96,13 @@
   }
 
   scoped_refptr<media::AudioRendererMixerInput> CreateInputHelper(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const base::UnguessableToken& session_id,
       const std::string& device_id,
       media::AudioLatency::LatencyType latency,
       const media::AudioParameters params,
       media::AudioRendererSink::RenderCallback* callback) {
-    auto input = manager_->CreateInput(source_render_frame_id, session_id,
+    auto input = manager_->CreateInput(source_frame_token, session_id,
                                        device_id, latency);
     input->GetOutputDeviceInfoAsync(
         base::DoNothing());  // Primes input, needed for tests.
@@ -114,7 +116,7 @@
 
  protected:
   scoped_refptr<media::MockAudioRendererSink> GetSink(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const media::AudioSinkParameters& params) {
     if ((params.device_id == kDefaultDeviceId) ||
         (params.device_id == kAnotherDeviceId)) {
@@ -143,9 +145,9 @@
 
  private:
   scoped_refptr<media::AudioRendererSink> GetPlainSink(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const media::AudioSinkParameters& params) {
-    return GetSink(source_render_frame_id, params);
+    return GetSink(source_frame_token, params);
   }
 
   DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest);
@@ -161,14 +163,14 @@
                                  kChannelLayout, kSampleRate, kBufferSize);
 
   media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params1, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(1, mixer_count());
 
   // The same parameters should return the same mixer1.
   EXPECT_EQ(mixer1,
-            GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
+            GetMixer(kFrameToken, params1, AudioLatency::LATENCY_PLAYBACK,
                      kDefaultDeviceId, SinkUseState::kExistingSink));
   EXPECT_EQ(1, mixer_count());
 
@@ -180,7 +182,7 @@
                                  kAnotherChannelLayout, kSampleRate * 2,
                                  kBufferSize * 2);
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params2, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params2, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(2, mixer_count());
@@ -205,7 +207,7 @@
                                  kSampleRate,
                                  kBufferSize);
   media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params1, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(1, mixer_count());
@@ -217,7 +219,7 @@
                                  kSampleRate * 2,
                                  kBufferSize * 2);
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params2, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params2, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kExistingSink);
   EXPECT_EQ(mixer1, mixer2);
   EXPECT_EQ(1, mixer_count());
@@ -231,7 +233,7 @@
                                  kBufferSize);
   ASSERT_NE(params3.channel_layout(), params1.channel_layout());
   media::AudioRendererMixer* mixer3 =
-      GetMixer(kRenderFrameId, params3, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params3, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   EXPECT_NE(mixer1, mixer3);
   EXPECT_EQ(2, mixer_count());
@@ -256,9 +258,9 @@
   media::FakeAudioRenderCallback callback(0, kSampleRate);
   mock_sink_ = CreateNormalSink();
   EXPECT_CALL(*mock_sink_, Start()).Times(1);
-  auto input = CreateInputHelper(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId,
-      AudioLatency::LATENCY_PLAYBACK, params, &callback);
+  auto input =
+      CreateInputHelper(kFrameToken, base::UnguessableToken(), kDefaultDeviceId,
+                        AudioLatency::LATENCY_PLAYBACK, params, &callback);
   EXPECT_EQ(0, mixer_count());
   media::FakeAudioRenderCallback another_callback(1, kSampleRate);
 
@@ -266,7 +268,7 @@
   mock_sink_ = CreateNormalSink();
   EXPECT_CALL(*mock_sink_, Start()).Times(1);
   auto another_input = CreateInputHelper(
-      kAnotherRenderFrameId, base::UnguessableToken(), kDefaultDeviceId,
+      kAnotherFrameToken, base::UnguessableToken(), kDefaultDeviceId,
       AudioLatency::LATENCY_PLAYBACK, params, &another_callback);
   EXPECT_EQ(0, mixer_count());
 
@@ -300,26 +302,26 @@
 
   // Empty device id, zero session id;
   auto input_to_default_device = CreateInputHelper(
-      kRenderFrameId, base::UnguessableToken(),  // session_id
+      kFrameToken, base::UnguessableToken(),  // session_id
       std::string(), AudioLatency::LATENCY_PLAYBACK, params, &callback);
   EXPECT_EQ(0, mixer_count());
 
   // Specific device id, zero session id;
   auto input_to_another_device = CreateInputHelper(
-      kRenderFrameId, base::UnguessableToken(),  // session_id
+      kFrameToken, base::UnguessableToken(),  // session_id
       kMatchedDeviceId, AudioLatency::LATENCY_PLAYBACK, params, &callback);
   EXPECT_EQ(0, mixer_count());
 
   // Specific device id, non-zero session id (to be ignored);
   auto input_to_matched_device = CreateInputHelper(
-      kRenderFrameId,
+      kFrameToken,
       base::UnguessableToken::Create(),  // session id
       kAnotherDeviceId, AudioLatency::LATENCY_PLAYBACK, params, &callback);
   EXPECT_EQ(0, mixer_count());
 
   // Empty device id, non-zero session id;
   auto input_to_matched_device_with_session_id = CreateInputHelper(
-      kRenderFrameId,
+      kFrameToken,
       base::UnguessableToken::Create(),  // session id
       std::string(), AudioLatency::LATENCY_PLAYBACK, params, &callback);
   EXPECT_EQ(0, mixer_count());
@@ -362,13 +364,13 @@
   media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                                 kChannelLayout, kSampleRate, kBufferSize);
   media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(1, mixer_count());
 
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kAnotherDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(2, mixer_count());
@@ -388,13 +390,13 @@
   media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                                 kChannelLayout, kSampleRate, kBufferSize);
   media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(1, mixer_count());
 
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                std::string(), SinkUseState::kExistingSink);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(1, mixer_count());
@@ -414,9 +416,9 @@
   media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                                 kChannelLayout, kSampleRate, kBufferSize);
 
-  auto sink = GetSink(kRenderFrameId,
-                      media::AudioSinkParameters(base::UnguessableToken(),
-                                                 kNonexistentDeviceId));
+  auto sink =
+      GetSink(kFrameToken, media::AudioSinkParameters(base::UnguessableToken(),
+                                                      kNonexistentDeviceId));
   auto device_info = sink->GetOutputDeviceInfo();
 
   EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
@@ -432,39 +434,39 @@
   media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                                 kChannelLayout, kSampleRate, kBufferSize);
   media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(1, mixer_count());
 
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kExistingSink);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(mixer1, mixer2);  // Same latency => same mixer.
   EXPECT_EQ(1, mixer_count());
 
   media::AudioRendererMixer* mixer3 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
-               kDefaultDeviceId, SinkUseState::kNewSink);
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_RTC, kDefaultDeviceId,
+               SinkUseState::kNewSink);
   ASSERT_TRUE(mixer3);
   EXPECT_NE(mixer1, mixer3);
   EXPECT_EQ(2, mixer_count());  // Another latency => another mixer.
 
   media::AudioRendererMixer* mixer4 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
-               kDefaultDeviceId, SinkUseState::kExistingSink);
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_RTC, kDefaultDeviceId,
+               SinkUseState::kExistingSink);
   EXPECT_EQ(mixer3, mixer4);
   EXPECT_EQ(2, mixer_count());  // Same latency => same mixer.
 
   media::AudioRendererMixer* mixer5 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_INTERACTIVE,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer5);
   EXPECT_EQ(3, mixer_count());  // Another latency => another mixer.
 
   media::AudioRendererMixer* mixer6 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_INTERACTIVE,
                kDefaultDeviceId, SinkUseState::kExistingSink);
   EXPECT_EQ(mixer5, mixer6);
   EXPECT_EQ(3, mixer_count());  // Same latency => same mixer.
@@ -492,13 +494,13 @@
                                 kChannelLayout, kSampleRate, kBufferSize);
   params.set_effects(1);
   media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(1, mixer_count());
 
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kExistingSink);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(mixer1, mixer2);  // Same effects => same mixer.
@@ -506,27 +508,27 @@
 
   params.set_effects(2);
   media::AudioRendererMixer* mixer3 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer3);
   EXPECT_NE(mixer1, mixer3);
   EXPECT_EQ(2, mixer_count());  // Another effects => another mixer.
 
   media::AudioRendererMixer* mixer4 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kExistingSink);
   EXPECT_EQ(mixer3, mixer4);
   EXPECT_EQ(2, mixer_count());  // Same effects => same mixer.
 
   params.set_effects(3);
   media::AudioRendererMixer* mixer5 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
   ASSERT_TRUE(mixer5);
   EXPECT_EQ(3, mixer_count());  // Another effects => another mixer.
 
   media::AudioRendererMixer* mixer6 =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kExistingSink);
   EXPECT_EQ(mixer5, mixer6);
   EXPECT_EQ(3, mixer_count());  // Same effects => same mixer.
@@ -563,7 +565,7 @@
   params.set_latency_tag(AudioLatency::LATENCY_PLAYBACK);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
+      GetMixer(kFrameToken, params, params.latency_tag(), kDefaultDeviceId,
                SinkUseState::kNewSink);
 
   if (AudioLatency::IsResamplingPassthroughSupported(params.latency_tag())) {
@@ -604,7 +606,7 @@
   params.set_latency_tag(AudioLatency::LATENCY_PLAYBACK);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
+      GetMixer(kFrameToken, params, params.latency_tag(), kDefaultDeviceId,
                SinkUseState::kNewSink);
 
   // 20 ms at 44100 is 882 frames per buffer.
@@ -635,7 +637,7 @@
                                 kChannelLayout, 32000, 512);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_PLAYBACK,
                kDefaultDeviceId, SinkUseState::kNewSink);
 
   // Expecting input sample rate
@@ -670,7 +672,7 @@
   params.set_latency_tag(AudioLatency::LATENCY_RTC);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
+      GetMixer(kFrameToken, params, params.latency_tag(), kDefaultDeviceId,
                SinkUseState::kNewSink);
 
   int output_sample_rate =
@@ -709,8 +711,8 @@
                                 kChannelLayout, 32000, 512);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
-               kDefaultDeviceId, SinkUseState::kNewSink);
+      GetMixer(kFrameToken, params, AudioLatency::LATENCY_RTC, kDefaultDeviceId,
+               SinkUseState::kNewSink);
 
   // Expecting input sample rate.
   EXPECT_EQ(32000, mixer->get_output_params_for_testing().sample_rate());
@@ -740,7 +742,7 @@
   params.set_latency_tag(AudioLatency::LATENCY_INTERACTIVE);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
+      GetMixer(kFrameToken, params, params.latency_tag(), kDefaultDeviceId,
                SinkUseState::kNewSink);
 
   if (AudioLatency::IsResamplingPassthroughSupported(params.latency_tag())) {
@@ -771,7 +773,7 @@
   params.set_latency_tag(AudioLatency::LATENCY_PLAYBACK);
 
   media::AudioRendererMixer* mixer =
-      GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
+      GetMixer(kFrameToken, params, params.latency_tag(), kDefaultDeviceId,
                SinkUseState::kNewSink);
 
   // Output parameters should be the same as input properties for bitstream
diff --git a/content/renderer/media/audio/audio_renderer_sink_cache.h b/content/renderer/media/audio/audio_renderer_sink_cache.h
index 6ba9a365..958b35b0 100644
--- a/content/renderer/media/audio/audio_renderer_sink_cache.h
+++ b/content/renderer/media/audio/audio_renderer_sink_cache.h
@@ -34,7 +34,7 @@
 
   // Returns output device information for a specified sink.
   virtual media::OutputDeviceInfo GetSinkInfo(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const base::UnguessableToken& session_id,
       const std::string& device_id) = 0;
 
@@ -42,7 +42,7 @@
   // calling ReleaseSink(). The sink must be stopped by the user before
   // deletion, but after releasing it from the cache.
   virtual scoped_refptr<media::AudioRendererSink> GetSink(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const std::string& device_id) = 0;
 
   // Notifies the cache that the sink is not in use any more. Must be
diff --git a/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc b/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc
index 3fa811c..4f07702 100644
--- a/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc
+++ b/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc
@@ -21,6 +21,7 @@
 #include "content/renderer/media/audio/audio_device_factory.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/audio_renderer_sink.h"
+#include "third_party/blink/public/web/web_local_frame.h"
 
 namespace content {
 
@@ -44,8 +45,13 @@
   }
 
   void DropFrameCache() {
-    if (AudioRendererSinkCacheImpl::instance_)
-      AudioRendererSinkCacheImpl::instance_->DropSinksForFrame(routing_id());
+    if (!AudioRendererSinkCacheImpl::instance_)
+      return;
+    if (!render_frame())
+      return;
+    base::UnguessableToken frame_token =
+        render_frame()->GetWebFrame()->GetFrameToken();
+    AudioRendererSinkCacheImpl::instance_->DropSinksForFrame(frame_token);
   }
 
   DISALLOW_COPY_AND_ASSIGN(FrameObserver);
@@ -77,7 +83,7 @@
 
 // Cached sink data.
 struct AudioRendererSinkCacheImpl::CacheEntry {
-  int source_render_frame_id;
+  base::UnguessableToken source_frame_token;
   std::string device_id;
   scoped_refptr<media::AudioRendererSink> sink;  // Sink instance
   bool used;                                     // True if in use by a client.
@@ -111,11 +117,11 @@
 }
 
 media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const base::UnguessableToken& session_id,
     const std::string& device_id) {
   TRACE_EVENT_BEGIN2("audio", "AudioRendererSinkCacheImpl::GetSinkInfo",
-                     "frame_id", source_render_frame_id, "device id",
+                     "frame_token", source_frame_token.ToString(), "device id",
                      device_id);
 
   if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
@@ -123,9 +129,9 @@
     // We are provided with session id instead of device id. Session id is
     // unique, so we can't find any matching sink. Creating a new one.
     scoped_refptr<media::AudioRendererSink> sink =
-        create_sink_cb_.Run(source_render_frame_id, {session_id, device_id});
+        create_sink_cb_.Run(source_frame_token, {session_id, device_id});
 
-    CacheOrStopUnusedSink(source_render_frame_id,
+    CacheOrStopUnusedSink(source_frame_token,
                           sink->GetOutputDeviceInfo().device_id(), sink);
 
     UMA_HISTOGRAM_ENUMERATION(
@@ -139,7 +145,7 @@
   // Ignore session id.
   {
     base::AutoLock auto_lock(cache_lock_);
-    auto cache_iter = FindCacheEntry_Locked(source_render_frame_id, device_id,
+    auto cache_iter = FindCacheEntry_Locked(source_frame_token, device_id,
                                             false /* unused_only */);
     if (cache_iter != cache_.end()) {
       // A matching cached sink is found.
@@ -154,10 +160,10 @@
 
   // No matching sink found, create a new one.
   scoped_refptr<media::AudioRendererSink> sink = create_sink_cb_.Run(
-      source_render_frame_id,
+      source_frame_token,
       media::AudioSinkParameters(base::UnguessableToken(), device_id));
 
-  CacheOrStopUnusedSink(source_render_frame_id, device_id, sink);
+  CacheOrStopUnusedSink(source_frame_token, device_id, sink);
 
   UMA_HISTOGRAM_ENUMERATION(
       "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
@@ -171,16 +177,17 @@
 }
 
 scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const std::string& device_id) {
   UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
                         true);
-  TRACE_EVENT_BEGIN2("audio", "AudioRendererSinkCacheImpl::GetSink", "frame_id",
-                     source_render_frame_id, "device id", device_id);
+  TRACE_EVENT_BEGIN2("audio", "AudioRendererSinkCacheImpl::GetSink",
+                     "frame_token", source_frame_token.ToString(), "device id",
+                     device_id);
 
   base::AutoLock auto_lock(cache_lock_);
 
-  auto cache_iter = FindCacheEntry_Locked(source_render_frame_id, device_id,
+  auto cache_iter = FindCacheEntry_Locked(source_frame_token, device_id,
                                           true /* unused sink only */);
 
   if (cache_iter != cache_.end()) {
@@ -195,9 +202,9 @@
 
   // No unused sink is found, create one, mark it used, cache it and return.
   CacheEntry cache_entry = {
-      source_render_frame_id, device_id,
+      source_frame_token, device_id,
       create_sink_cb_.Run(
-          source_render_frame_id,
+          source_frame_token,
           media::AudioSinkParameters(base::UnguessableToken(), device_id)),
       // media::AudioSinkParameters(kDefaultSessionId, device_id)),
       true /* used */};
@@ -279,15 +286,15 @@
 
 AudioRendererSinkCacheImpl::CacheContainer::iterator
 AudioRendererSinkCacheImpl::FindCacheEntry_Locked(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const std::string& device_id,
     bool unused_only) {
   return std::find_if(
       cache_.begin(), cache_.end(),
-      [source_render_frame_id, &device_id, unused_only](const CacheEntry& val) {
+      [source_frame_token, &device_id, unused_only](const CacheEntry& val) {
         if (val.used && unused_only)
           return false;
-        if (val.source_render_frame_id != source_render_frame_id)
+        if (val.source_frame_token != source_frame_token)
           return false;
         if (media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
             media::AudioDeviceDescription::IsDefaultDevice(val.device_id)) {
@@ -300,7 +307,7 @@
 }
 
 void AudioRendererSinkCacheImpl::CacheOrStopUnusedSink(
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     const std::string& device_id,
     scoped_refptr<media::AudioRendererSink> sink) {
   if (!SinkIsHealthy(sink.get())) {
@@ -311,7 +318,7 @@
     return;
   }
 
-  CacheEntry cache_entry = {source_render_frame_id, device_id, std::move(sink),
+  CacheEntry cache_entry = {source_frame_token, device_id, std::move(sink),
                             false /* not used */};
 
   {
@@ -322,10 +329,11 @@
   DeleteLaterIfUnused(cache_entry.sink.get());
 }
 
-void AudioRendererSinkCacheImpl::DropSinksForFrame(int source_render_frame_id) {
+void AudioRendererSinkCacheImpl::DropSinksForFrame(
+    const base::UnguessableToken& source_frame_token) {
   base::AutoLock auto_lock(cache_lock_);
-  base::EraseIf(cache_, [source_render_frame_id](const CacheEntry& val) {
-    if (val.source_render_frame_id == source_render_frame_id) {
+  base::EraseIf(cache_, [source_frame_token](const CacheEntry& val) {
+    if (val.source_frame_token == source_frame_token) {
       val.sink->Stop();
       return true;
     }
diff --git a/content/renderer/media/audio/audio_renderer_sink_cache_impl.h b/content/renderer/media/audio/audio_renderer_sink_cache_impl.h
index 1712f56b..a54d0781a 100644
--- a/content/renderer/media/audio/audio_renderer_sink_cache_impl.h
+++ b/content/renderer/media/audio/audio_renderer_sink_cache_impl.h
@@ -28,7 +28,7 @@
   // Callback to be used for AudioRendererSink creation
   using CreateSinkCallback =
       base::RepeatingCallback<scoped_refptr<media::AudioRendererSink>(
-          int render_frame_id,
+          const base::UnguessableToken& frame_token,
           const media::AudioSinkParameters& params)>;
 
   // |cleanup_task_runner| will be used to delete sinks when they are unused,
@@ -41,12 +41,13 @@
 
   ~AudioRendererSinkCacheImpl() final;
 
-  media::OutputDeviceInfo GetSinkInfo(int source_render_frame_id,
-                                      const base::UnguessableToken& session_id,
-                                      const std::string& device_id) final;
+  media::OutputDeviceInfo GetSinkInfo(
+      const base::UnguessableToken& source_frame_token,
+      const base::UnguessableToken& session_id,
+      const std::string& device_id) final;
 
   scoped_refptr<media::AudioRendererSink> GetSink(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const std::string& device_id) final;
 
   void ReleaseSink(const media::AudioRendererSink* sink_ptr) final;
@@ -70,15 +71,15 @@
                   bool force_delete_used);
 
   CacheContainer::iterator FindCacheEntry_Locked(
-      int source_render_frame_id,
+      const base::UnguessableToken& source_frame_token,
       const std::string& device_id,
       bool unused_only);
 
-  void CacheOrStopUnusedSink(int source_render_frame_id,
+  void CacheOrStopUnusedSink(const base::UnguessableToken& source_frame_token,
                              const std::string& device_id,
                              scoped_refptr<media::AudioRendererSink> sink);
 
-  void DropSinksForFrame(int source_render_frame_id);
+  void DropSinksForFrame(const base::UnguessableToken& source_frame_token);
 
   // To avoid publishing CacheEntry structure in the header.
   int GetCacheSizeForTesting();
diff --git a/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc b/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
index f2e459ff..68e949c 100644
--- a/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
+++ b/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
@@ -24,7 +24,7 @@
     media::AudioDeviceDescription::kDefaultDeviceId;
 const char kAnotherDeviceId[] = "another-device-id";
 const char kUnhealthyDeviceId[] = "i-am-sick";
-const int kRenderFrameId = 124;
+const base::UnguessableToken kFrameToken = base::UnguessableToken::Create();
 constexpr base::TimeDelta kDeleteTimeout =
     base::TimeDelta::FromMilliseconds(500);
 }  // namespace
@@ -43,10 +43,10 @@
     task_env_.FastForwardUntilNoTasksRemain();
   }
 
-  void GetSink(int render_frame_id,
+  void GetSink(const base::UnguessableToken& frame_token,
                const std::string& device_id,
                media::AudioRendererSink** sink) {
-    *sink = cache_->GetSink(render_frame_id, device_id).get();
+    *sink = cache_->GetSink(frame_token, device_id).get();
   }
 
  protected:
@@ -56,7 +56,7 @@
   }
 
   scoped_refptr<media::AudioRendererSink> CreateSink(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params) {
     return new testing::NiceMock<media::MockAudioRendererSink>(
         params.device_id, (params.device_id == kUnhealthyDeviceId)
@@ -85,7 +85,9 @@
     e.Wait();
   }
 
-  void DropSinksForFrame(int frame_id) { cache_->DropSinksForFrame(frame_id); }
+  void DropSinksForFrame(const base::UnguessableToken& frame_token) {
+    cache_->DropSinksForFrame(frame_token);
+  }
 
   base::test::TaskEnvironment task_env_;
   std::unique_ptr<AudioRendererSinkCacheImpl> cache_;
@@ -99,14 +101,14 @@
   // Verify that a new sink is successfully created.
   EXPECT_EQ(0, sink_count());
   scoped_refptr<media::AudioRendererSink> sink =
-      cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
+      cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
   ExpectNotToStop(sink.get());  // Cache should not stop sinks marked as used.
   EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
   EXPECT_EQ(1, sink_count());
 
   // Verify that another sink with the same key is successfully created
   scoped_refptr<media::AudioRendererSink> another_sink =
-      cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
+      cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
   ExpectNotToStop(another_sink.get());
   EXPECT_EQ(kDefaultDeviceId, another_sink->GetOutputDeviceInfo().device_id());
   EXPECT_EQ(2, sink_count());
@@ -114,7 +116,7 @@
 
   // Verify that another sink with a different kay is successfully created.
   scoped_refptr<media::AudioRendererSink> yet_another_sink =
-      cache_->GetSink(kRenderFrameId, kAnotherDeviceId).get();
+      cache_->GetSink(kFrameToken, kAnotherDeviceId).get();
   ExpectNotToStop(yet_another_sink.get());
   EXPECT_EQ(kAnotherDeviceId,
             yet_another_sink->GetOutputDeviceInfo().device_id());
@@ -147,32 +149,32 @@
 TEST_F(AudioRendererSinkCacheTest, GetDeviceInfo) {
   EXPECT_EQ(0, sink_count());
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId);
+      kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
   EXPECT_EQ(1, sink_count());
 
   // The info on the same device is requested, so no new sink is created.
   media::OutputDeviceInfo one_more_device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId);
+      kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
   EXPECT_EQ(1, sink_count());
   EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
 
   // Aquire the sink that was created on GetSinkInfo().
   scoped_refptr<media::AudioRendererSink> sink =
-      cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
+      cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
   EXPECT_EQ(1, sink_count());
   EXPECT_EQ(device_info.device_id(), sink->GetOutputDeviceInfo().device_id());
 
   // Now the sink is in used, but we can still get the device info out of it, no
   // new sink is created.
   one_more_device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId);
+      kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
   EXPECT_EQ(1, sink_count());
   EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
 
   // Request sink for the same device. The first sink is in use, so a new one
   // should be created.
   scoped_refptr<media::AudioRendererSink> another_sink =
-      cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
+      cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
   EXPECT_EQ(2, sink_count());
   EXPECT_EQ(device_info.device_id(),
             another_sink->GetOutputDeviceInfo().device_id());
@@ -183,11 +185,11 @@
   EXPECT_EQ(0, sink_count());
 
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId);
+      kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
   EXPECT_EQ(1, sink_count());
 
   media::OutputDeviceInfo another_device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kAnotherDeviceId);
+      kFrameToken, base::UnguessableToken(), kAnotherDeviceId);
   EXPECT_EQ(2, sink_count());
 
   // Wait for garbage collection. Doesn't actually sleep, just advances the mock
@@ -204,7 +206,7 @@
   EXPECT_EQ(0, sink_count());
 
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId);
+      kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
   EXPECT_EQ(1, sink_count());
 
   // Wait less than garbage collection timeout.
@@ -217,7 +219,7 @@
 
   // Request it:
   scoped_refptr<media::AudioRendererSink> sink =
-      cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
+      cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
   EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
   EXPECT_EQ(1, sink_count());
 
@@ -233,10 +235,10 @@
 TEST_F(AudioRendererSinkCacheTest, UnhealthySinkIsNotCached) {
   EXPECT_EQ(0, sink_count());
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kUnhealthyDeviceId);
+      kFrameToken, base::UnguessableToken(), kUnhealthyDeviceId);
   EXPECT_EQ(0, sink_count());
   scoped_refptr<media::AudioRendererSink> sink =
-      cache_->GetSink(kRenderFrameId, kUnhealthyDeviceId).get();
+      cache_->GetSink(kFrameToken, kUnhealthyDeviceId).get();
   EXPECT_EQ(0, sink_count());
 }
 
@@ -251,9 +253,10 @@
   cache_ = std::make_unique<AudioRendererSinkCacheImpl>(
       task_env_.GetMainThreadTaskRunner(),
       base::BindRepeating(
-          [](scoped_refptr<media::AudioRendererSink> sink, int render_frame_id,
+          [](scoped_refptr<media::AudioRendererSink> sink,
+             const base::UnguessableToken& frame_token,
              const media::AudioSinkParameters& params) {
-            EXPECT_EQ(kRenderFrameId, render_frame_id);
+            EXPECT_EQ(kFrameToken, frame_token);
             EXPECT_TRUE(params.session_id.is_empty());
             EXPECT_EQ(kUnhealthyDeviceId, params.device_id);
             return sink;
@@ -264,7 +267,7 @@
   EXPECT_CALL(*sink, Stop());
 
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kUnhealthyDeviceId);
+      kFrameToken, base::UnguessableToken(), kUnhealthyDeviceId);
 }
 
 // Verify that a sink created with GetSinkInfo() is stopped even if it's
@@ -278,9 +281,10 @@
   cache_ = std::make_unique<AudioRendererSinkCacheImpl>(
       task_env_.GetMainThreadTaskRunner(),
       base::BindRepeating(
-          [](scoped_refptr<media::AudioRendererSink> sink, int render_frame_id,
+          [](scoped_refptr<media::AudioRendererSink> sink,
+             const base::UnguessableToken& frame_token,
              const media::AudioSinkParameters& params) {
-            EXPECT_EQ(kRenderFrameId, render_frame_id);
+            EXPECT_EQ(kFrameToken, frame_token);
             EXPECT_TRUE(!params.session_id.is_empty());
             EXPECT_TRUE(params.device_id.empty());
             return sink;
@@ -291,7 +295,7 @@
   EXPECT_CALL(*sink, Stop());
 
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken::Create(), std::string());
+      kFrameToken, base::UnguessableToken::Create(), std::string());
 }
 
 // Verify that cache works fine if a sink scheduled for deletion is acquired and
@@ -303,12 +307,12 @@
   thread.Start();
 
   media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kDefaultDeviceId);
+      kFrameToken, base::UnguessableToken(), kDefaultDeviceId);
   EXPECT_EQ(1, sink_count());  // This sink is scheduled for deletion now.
 
   // Request it:
   scoped_refptr<media::AudioRendererSink> sink =
-      cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
+      cache_->GetSink(kFrameToken, kDefaultDeviceId).get();
   ExpectNotToStop(sink.get());
   EXPECT_EQ(1, sink_count());
 
@@ -317,7 +321,7 @@
   EXPECT_EQ(0, sink_count());
 
   media::OutputDeviceInfo another_device_info = cache_->GetSinkInfo(
-      kRenderFrameId, base::UnguessableToken(), kAnotherDeviceId);
+      kFrameToken, base::UnguessableToken(), kAnotherDeviceId);
   EXPECT_EQ(1, sink_count());  // This sink is scheduled for deletion now.
 
   task_env_.FastForwardBy(kDeleteTimeout);
@@ -341,7 +345,7 @@
   PostAndWaitUntilDone(
       thread1, base::BindOnce(
                    base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
-                   base::Unretained(cache_.get()), kRenderFrameId,
+                   base::Unretained(cache_.get()), kFrameToken,
                    base::UnguessableToken(), kDefaultDeviceId));
 
   EXPECT_EQ(1, sink_count());
@@ -351,7 +355,7 @@
 
   PostAndWaitUntilDone(thread2,
                        base::BindOnce(&AudioRendererSinkCacheTest::GetSink,
-                                      base::Unretained(this), kRenderFrameId,
+                                      base::Unretained(this), kFrameToken,
                                       kDefaultDeviceId, &sink));
 
   EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
@@ -361,7 +365,7 @@
   PostAndWaitUntilDone(
       thread1, base::BindOnce(
                    base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
-                   base::Unretained(cache_.get()), kRenderFrameId,
+                   base::Unretained(cache_.get()), kFrameToken,
                    base::UnguessableToken(), kDefaultDeviceId));
   EXPECT_EQ(1, sink_count());
 
@@ -377,30 +381,30 @@
 TEST_F(AudioRendererSinkCacheTest, StopsAndDropsSinks) {
   EXPECT_EQ(0, sink_count());
   scoped_refptr<media::AudioRendererSink> sink1 =
-      cache_->GetSink(kRenderFrameId, "device1").get();
+      cache_->GetSink(kFrameToken, "device1").get();
   scoped_refptr<media::AudioRendererSink> sink2 =
-      cache_->GetSink(kRenderFrameId, "device2").get();
+      cache_->GetSink(kFrameToken, "device2").get();
   EXPECT_EQ(2, sink_count());
 
   EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink1.get()), Stop());
   EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink2.get()), Stop());
-  DropSinksForFrame(kRenderFrameId);
+  DropSinksForFrame(kFrameToken);
   EXPECT_EQ(0, sink_count());
 }
 
 TEST_F(AudioRendererSinkCacheTest, StopsAndDropsCorrectSinks) {
   EXPECT_EQ(0, sink_count());
   scoped_refptr<media::AudioRendererSink> sink1 =
-      cache_->GetSink(kRenderFrameId, "device1").get();
+      cache_->GetSink(kFrameToken, "device1").get();
   scoped_refptr<media::AudioRendererSink> another_sink =
-      cache_->GetSink(kRenderFrameId + 1, "device1").get();
+      cache_->GetSink(base::UnguessableToken::Create(), "device1").get();
   scoped_refptr<media::AudioRendererSink> sink2 =
-      cache_->GetSink(kRenderFrameId, "device2").get();
+      cache_->GetSink(kFrameToken, "device2").get();
   EXPECT_EQ(3, sink_count());
 
   EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink1.get()), Stop());
   EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink2.get()), Stop());
-  DropSinksForFrame(kRenderFrameId);
+  DropSinksForFrame(kFrameToken);
   EXPECT_EQ(1, sink_count());
   EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(another_sink.get()),
               Stop());
diff --git a/content/renderer/media/audio/fuchsia_audio_device_factory.cc b/content/renderer/media/audio/fuchsia_audio_device_factory.cc
index a51ae9b..9a703c8 100644
--- a/content/renderer/media/audio/fuchsia_audio_device_factory.cc
+++ b/content/renderer/media/audio/fuchsia_audio_device_factory.cc
@@ -14,6 +14,7 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/web/web_frame.h"
 
 namespace content {
 
@@ -22,7 +23,7 @@
 
 scoped_refptr<media::AudioRendererSink>
 FuchsiaAudioDeviceFactory::CreateFinalAudioRendererSink(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params,
     base::TimeDelta auth_timeout) {
   // Return nullptr to fallback to the default renderer implementation.
@@ -32,7 +33,7 @@
 scoped_refptr<media::AudioRendererSink>
 FuchsiaAudioDeviceFactory::CreateAudioRendererSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   // Return nullptr to fallback to the default renderer implementation.
   return nullptr;
@@ -41,7 +42,7 @@
 scoped_refptr<media::SwitchableAudioRendererSink>
 FuchsiaAudioDeviceFactory::CreateSwitchableAudioRendererSink(
     blink::WebAudioDeviceSourceType source_type,
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSinkParameters& params) {
   // Return nullptr to fallback to the default renderer implementation.
   return nullptr;
@@ -49,8 +50,13 @@
 
 scoped_refptr<media::AudioCapturerSource>
 FuchsiaAudioDeviceFactory::CreateAudioCapturerSource(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSourceParameters& params) {
+  blink::WebFrame* web_frame = blink::WebFrame::FromFrameToken(frame_token);
+  if (!web_frame)
+    return nullptr;
+
+  int render_frame_id = RenderFrame::GetRoutingIdForWebFrame(web_frame);
   auto* render_frame = RenderFrame::FromRoutingID(render_frame_id);
   if (!render_frame)
     return nullptr;
diff --git a/content/renderer/media/audio/fuchsia_audio_device_factory.h b/content/renderer/media/audio/fuchsia_audio_device_factory.h
index 50cd738..7966d10 100644
--- a/content/renderer/media/audio/fuchsia_audio_device_factory.h
+++ b/content/renderer/media/audio/fuchsia_audio_device_factory.h
@@ -16,23 +16,23 @@
 
  protected:
   scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params,
       base::TimeDelta auth_timeout) final;
 
   scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params) final;
 
   scoped_refptr<media::SwitchableAudioRendererSink>
   CreateSwitchableAudioRendererSink(
       blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params) final;
 
   scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSourceParameters& params) final;
 };
 
diff --git a/content/renderer/media/audio/mock_audio_device_factory.cc b/content/renderer/media/audio/mock_audio_device_factory.cc
index 2a8930f9..b6fdea9 100644
--- a/content/renderer/media/audio/mock_audio_device_factory.cc
+++ b/content/renderer/media/audio/mock_audio_device_factory.cc
@@ -23,7 +23,7 @@
 
 scoped_refptr<media::AudioCapturerSource>
 MockAudioDeviceFactory::CreateAudioCapturerSource(
-    int render_frame_id,
+    const base::UnguessableToken& frame_token,
     const media::AudioSourceParameters& params) {
   CHECK(!did_create_once_);
   did_create_once_ = true;
diff --git a/content/renderer/media/audio/mock_audio_device_factory.h b/content/renderer/media/audio/mock_audio_device_factory.h
index faf49c1..9e11a84 100644
--- a/content/renderer/media/audio/mock_audio_device_factory.h
+++ b/content/renderer/media/audio/mock_audio_device_factory.h
@@ -48,24 +48,24 @@
   // implemented.
   MOCK_METHOD3(CreateFinalAudioRendererSink,
                scoped_refptr<media::AudioRendererSink>(
-                   int render_frame_id,
+                   const base::UnguessableToken& frame_token,
                    const media::AudioSinkParameters& params,
                    base::TimeDelta auth_timeout));
   MOCK_METHOD3(CreateAudioRendererSink,
                scoped_refptr<media::AudioRendererSink>(
                    blink::WebAudioDeviceSourceType source_type,
-                   int render_frame_id,
+                   const base::UnguessableToken& frame_token,
                    const media::AudioSinkParameters& params));
   MOCK_METHOD3(CreateSwitchableAudioRendererSink,
                scoped_refptr<media::SwitchableAudioRendererSink>(
                    blink::WebAudioDeviceSourceType source_type,
-                   int render_frame_id,
+                   const base::UnguessableToken& frame_token,
                    const media::AudioSinkParameters& params));
 
   // Returns mock_capturer_source_ once. If called a second time, the process
   // will crash.
   scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
-      int render_frame_id,
+      const base::UnguessableToken& frame_token,
       const media::AudioSourceParameters& params) override;
 
  private:
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index b218158..fc4e6d2 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -375,7 +375,7 @@
   scoped_refptr<media::SwitchableAudioRendererSink> audio_renderer_sink =
       AudioDeviceFactory::NewSwitchableAudioRendererSink(
           blink::WebAudioDeviceSourceType::kMediaElement,
-          render_frame_->GetRoutingID(),
+          render_frame_->GetWebFrame()->GetFrameToken(),
           media::AudioSinkParameters(/*session_id=*/base::UnguessableToken(),
                                      sink_id.Utf8()));
 
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc
index 7eefa1d..4a134b9 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -83,7 +83,7 @@
   return 0;
 }
 
-int FrameIdFromCurrentContext() {
+base::UnguessableToken FrameTokenFromCurrentContext() {
   // Assumption: This method is being invoked within a V8 call stack.  CHECKs
   // will fail in the call to frameForCurrentContext() otherwise.
   //
@@ -93,15 +93,14 @@
   // an extension creates a object that is passed and used within a page).
   blink::WebLocalFrame* const web_frame =
       blink::WebLocalFrame::FrameForCurrentContext();
-  RenderFrame* const render_frame = RenderFrame::FromWebFrame(web_frame);
-  return render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE;
+  return web_frame ? web_frame->GetFrameToken() : base::UnguessableToken();
 }
 
 media::AudioParameters GetOutputDeviceParameters(
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     const base::UnguessableToken& session_id,
     const std::string& device_id) {
-  return AudioDeviceFactory::GetOutputDeviceInfo(frame_id,
+  return AudioDeviceFactory::GetOutputDeviceInfo(frame_token,
                                                  {session_id, device_id})
       .output_params();
 }
@@ -118,7 +117,7 @@
       new RendererWebAudioDeviceImpl(
           layout, channels, latency_hint, callback, session_id,
           base::BindOnce(&GetOutputDeviceParameters),
-          base::BindOnce(&FrameIdFromCurrentContext)));
+          base::BindOnce(&FrameTokenFromCurrentContext)));
 }
 
 RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
@@ -128,16 +127,17 @@
     WebAudioDevice::RenderCallback* callback,
     const base::UnguessableToken& session_id,
     OutputDeviceParamsCallback device_params_cb,
-    RenderFrameIdCallback render_frame_id_cb)
+    RenderFrameTokenCallback render_frame_token_cb)
     : latency_hint_(latency_hint),
       client_callback_(callback),
       session_id_(session_id),
-      frame_id_(std::move(render_frame_id_cb).Run()) {
+      frame_token_(std::move(render_frame_token_cb).Run()) {
   DCHECK(client_callback_);
-  DCHECK(session_id.is_empty() || frame_id_ != MSG_ROUTING_NONE);
+  DCHECK(session_id.is_empty() || !frame_token_.is_empty());
 
   media::AudioParameters hardware_params(
-      std::move(device_params_cb).Run(frame_id_, session_id_, std::string()));
+      std::move(device_params_cb)
+          .Run(frame_token_, session_id_, std::string()));
 
   // On systems without audio hardware the returned parameters may be invalid.
   // In which case just choose whatever we want for the fake device.
@@ -176,7 +176,7 @@
     return;  // Already started.
 
   sink_ = AudioDeviceFactory::NewAudioRendererSink(
-      GetLatencyHintSourceType(latency_hint_.Category()), frame_id_,
+      GetLatencyHintSourceType(latency_hint_.Category()), frame_token_,
       media::AudioSinkParameters(session_id_, std::string()));
 
   // Use a task runner instead of the render thread for fake Render() calls
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.h b/content/renderer/media/renderer_webaudiodevice_impl.h
index 870cf49..f1efe7b 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -72,12 +72,12 @@
  protected:
   // Callback to get output device params (for tests).
   using OutputDeviceParamsCallback = base::OnceCallback<media::AudioParameters(
-      int frame_id,
+      const base::UnguessableToken& frame_token,
       const base::UnguessableToken& session_id,
       const std::string& device_id)>;
 
-  // Callback get render frame ID for current context (for tests).
-  using RenderFrameIdCallback = base::OnceCallback<int()>;
+  // Callback get render frame token for current context (for tests).
+  using RenderFrameTokenCallback = base::OnceCallback<base::UnguessableToken()>;
 
   RendererWebAudioDeviceImpl(media::ChannelLayout layout,
                              int channels,
@@ -85,7 +85,7 @@
                              blink::WebAudioDevice::RenderCallback* callback,
                              const base::UnguessableToken& session_id,
                              OutputDeviceParamsCallback device_params_cb,
-                             RenderFrameIdCallback render_frame_id_cb);
+                             RenderFrameTokenCallback render_frame_token_cb);
 
  private:
   scoped_refptr<base::SingleThreadTaskRunner> GetSuspenderTaskRunner();
@@ -110,8 +110,8 @@
   // Used to suspend |sink_| usage when silence has been detected for too long.
   std::unique_ptr<media::SilentSinkSuspender> webaudio_suspender_;
 
-  // Render frame routing ID for the current context.
-  int frame_id_;
+  // Render frame token for the current context.
+  base::UnguessableToken frame_token_;
 
   // Allow unit tests to set a custom TaskRunner for |webaudio_suspender_|.
   scoped_refptr<base::SingleThreadTaskRunner> suspender_task_runner_;
diff --git a/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc b/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
index 8d0e3ca..e638475 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
@@ -25,14 +25,14 @@
 
 const int kHardwareSampleRate = 44100;
 const int kHardwareBufferSize = 128;
-const int kRenderFrameId = 100;
+const base::UnguessableToken kFrameToken = base::UnguessableToken::Create();
 
-int MockFrameIdFromCurrentContext() {
-  return kRenderFrameId;
+base::UnguessableToken MockFrameTokenFromCurrentContext() {
+  return kFrameToken;
 }
 
 media::AudioParameters MockGetOutputDeviceParameters(
-    int frame_id,
+    const base::UnguessableToken& frame_token,
     const base::UnguessableToken& session_id,
     const std::string& device_id) {
   return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
@@ -55,7 +55,7 @@
             callback,
             session_id,
             base::BindOnce(&MockGetOutputDeviceParameters),
-            base::BindOnce(&MockFrameIdFromCurrentContext)) {}
+            base::BindOnce(&MockFrameTokenFromCurrentContext)) {}
 };
 
 }  // namespace
@@ -87,27 +87,27 @@
 
   MOCK_METHOD2(CreateAudioCapturerSource,
                scoped_refptr<media::AudioCapturerSource>(
-                   int,
+                   const base::UnguessableToken&,
                    const media::AudioSourceParameters&));
   MOCK_METHOD3(
       CreateFinalAudioRendererSink,
-      scoped_refptr<media::AudioRendererSink>(int,
+      scoped_refptr<media::AudioRendererSink>(const base::UnguessableToken&,
                                               const media::AudioSinkParameters&,
                                               base::TimeDelta));
   MOCK_METHOD3(CreateSwitchableAudioRendererSink,
                scoped_refptr<media::SwitchableAudioRendererSink>(
                    blink::WebAudioDeviceSourceType,
-                   int,
+                   const base::UnguessableToken&,
                    const media::AudioSinkParameters&));
 
   scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
-      blink::WebAudioDeviceSourceType source_type,
-      int render_frame_id,
+      blink::WebAudioDeviceSourceType render_token,
+      const base::UnguessableToken& frame_token,
       const media::AudioSinkParameters& params) override {
     scoped_refptr<media::MockAudioRendererSink> mock_sink =
         new media::MockAudioRendererSink(
             params.device_id, media::OUTPUT_DEVICE_STATUS_OK,
-            MockGetOutputDeviceParameters(render_frame_id, params.session_id,
+            MockGetOutputDeviceParameters(frame_token, params.session_id,
                                           params.device_id));
 
     EXPECT_CALL(*mock_sink.get(), Start());
diff --git a/content/renderer/pepper/pepper_platform_audio_input.cc b/content/renderer/pepper/pepper_platform_audio_input.cc
index 3a0d7f9..565d6bb 100644
--- a/content/renderer/pepper/pepper_platform_audio_input.cc
+++ b/content/renderer/pepper/pepper_platform_audio_input.cc
@@ -19,6 +19,7 @@
 #include "content/renderer/render_view_impl.h"
 #include "media/audio/audio_device_description.h"
 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
+#include "third_party/blink/public/web/web_local_frame.h"
 
 namespace content {
 
@@ -146,6 +147,7 @@
     return false;
 
   render_frame_id_ = render_frame_id;
+  render_frame_token_ = render_frame->GetWebFrame()->GetFrameToken();
   client_ = client;
 
   if (!GetMediaDeviceManager())
@@ -176,7 +178,7 @@
 
   if (ipc_startup_state_ != kStopped)
     ipc_ = AudioInputIPCFactory::get()->CreateAudioInputIPC(
-        render_frame_id_, media::AudioSourceParameters(session_id));
+        render_frame_token_, media::AudioSourceParameters(session_id));
   if (!ipc_)
     return;
 
diff --git a/content/renderer/pepper/pepper_platform_audio_input.h b/content/renderer/pepper/pepper_platform_audio_input.h
index 9bccf3d..338f0cf 100644
--- a/content/renderer/pepper/pepper_platform_audio_input.h
+++ b/content/renderer/pepper/pepper_platform_audio_input.h
@@ -103,6 +103,7 @@
 
   // The frame containing the Pepper widget.
   int render_frame_id_;
+  base::UnguessableToken render_frame_token_;
 
   // The unique ID to identify the opened device. THIS MUST ONLY BE ACCESSED ON
   // THE MAIN THREAD.
diff --git a/content/renderer/pepper/pepper_platform_audio_output.cc b/content/renderer/pepper/pepper_platform_audio_output.cc
index 8a058d1..e1f5a45d 100644
--- a/content/renderer/pepper/pepper_platform_audio_output.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output.cc
@@ -22,14 +22,12 @@
 PepperPlatformAudioOutput* PepperPlatformAudioOutput::Create(
     int sample_rate,
     int frames_per_buffer,
-    int source_render_frame_id,
+    const base::UnguessableToken& source_frame_token,
     AudioHelper* client) {
   scoped_refptr<PepperPlatformAudioOutput> audio_output(
       new PepperPlatformAudioOutput());
-  if (audio_output->Initialize(sample_rate,
-                               frames_per_buffer,
-                               source_render_frame_id,
-                               client)) {
+  if (audio_output->Initialize(sample_rate, frames_per_buffer,
+                               source_frame_token, client)) {
     // Balanced by Release invoked in
     // PepperPlatformAudioOutput::ShutDownOnIOThread().
     audio_output->AddRef();
@@ -130,15 +128,15 @@
       main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       io_task_runner_(ChildProcess::current()->io_task_runner()) {}
 
-bool PepperPlatformAudioOutput::Initialize(int sample_rate,
-                                           int frames_per_buffer,
-                                           int source_render_frame_id,
-                                           AudioHelper* client) {
+bool PepperPlatformAudioOutput::Initialize(
+    int sample_rate,
+    int frames_per_buffer,
+    const base::UnguessableToken& source_frame_token,
+    AudioHelper* client) {
   DCHECK(client);
   client_ = client;
 
-  ipc_ = AudioOutputIPCFactory::get()->CreateAudioOutputIPC(
-      source_render_frame_id);
+  ipc_ = AudioOutputIPCFactory::get()->CreateAudioOutputIPC(source_frame_token);
   CHECK(ipc_);
 
   media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
diff --git a/content/renderer/pepper/pepper_platform_audio_output.h b/content/renderer/pepper/pepper_platform_audio_output.h
index 1072193..678b5ddb 100644
--- a/content/renderer/pepper/pepper_platform_audio_output.h
+++ b/content/renderer/pepper/pepper_platform_audio_output.h
@@ -29,10 +29,11 @@
  public:
   // Factory function, returns NULL on failure. StreamCreated() will be called
   // when the stream is created.
-  static PepperPlatformAudioOutput* Create(int sample_rate,
-                                           int frames_per_buffer,
-                                           int source_render_frame_id,
-                                           AudioHelper* client);
+  static PepperPlatformAudioOutput* Create(
+      int sample_rate,
+      int frames_per_buffer,
+      const base::UnguessableToken& source_frame_token,
+      AudioHelper* client);
 
   // The following three methods are all called on main thread.
 
@@ -72,7 +73,7 @@
 
   bool Initialize(int sample_rate,
                   int frames_per_buffer,
-                  int source_render_frame_id,
+                  const base::UnguessableToken& source_frame_token,
                   AudioHelper* client);
 
   // I/O thread backends to above functions.
diff --git a/content/renderer/pepper/pepper_platform_audio_output_dev.cc b/content/renderer/pepper/pepper_platform_audio_output_dev.cc
index 4ec293cb..f885453 100644
--- a/content/renderer/pepper/pepper_platform_audio_output_dev.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output_dev.cc
@@ -21,6 +21,7 @@
 #include "content/renderer/render_frame_impl.h"
 #include "media/audio/audio_device_description.h"
 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
+#include "third_party/blink/public/web/web_local_frame.h"
 
 namespace {
 #if defined(OS_WIN) || defined(OS_MACOSX)
@@ -259,7 +260,8 @@
 
   client_ = client;
 
-  ipc_ = AudioOutputIPCFactory::get()->CreateAudioOutputIPC(render_frame_id_);
+  ipc_ = AudioOutputIPCFactory::get()->CreateAudioOutputIPC(
+      render_frame->GetWebFrame()->GetFrameToken());
   CHECK(ipc_);
 
   params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index a19c9f1..248a0ec 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -2517,7 +2517,7 @@
 uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputSampleRate(
     PP_Instance instance) {
   return render_frame() ? AudioDeviceFactory::GetOutputDeviceInfo(
-                              render_frame()->GetRoutingID(),
+                              render_frame()->GetWebFrame()->GetFrameToken(),
                               media::AudioSinkParameters())
                               .output_params()
                               .sample_rate()
@@ -2527,7 +2527,7 @@
 uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputBufferSize(
     PP_Instance instance) {
   return render_frame() ? AudioDeviceFactory::GetOutputDeviceInfo(
-                              render_frame()->GetRoutingID(),
+                              render_frame()->GetWebFrame()->GetFrameToken(),
                               media::AudioSinkParameters())
                               .output_params()
                               .frames_per_buffer()
diff --git a/content/renderer/pepper/ppb_audio_impl.cc b/content/renderer/pepper/ppb_audio_impl.cc
index cd91a13..389c3f2 100644
--- a/content/renderer/pepper/ppb_audio_impl.cc
+++ b/content/renderer/pepper/ppb_audio_impl.cc
@@ -17,6 +17,7 @@
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/ppb_audio_config_api.h"
 #include "ppapi/thunk/thunk.h"
+#include "third_party/blink/public/web/web_local_frame.h"
 
 using ppapi::PpapiGlobals;
 using ppapi::thunk::EnterResourceNoLock;
@@ -134,8 +135,7 @@
   audio_ = PepperPlatformAudioOutput::Create(
       static_cast<int>(enter.object()->GetSampleRate()),
       static_cast<int>(enter.object()->GetSampleFrameCount()),
-      instance->render_frame()->GetRoutingID(),
-      this);
+      instance->render_frame()->GetWebFrame()->GetFrameToken(), this);
   if (!audio_)
     return PP_ERROR_FAILED;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index e99f66b..695a1405 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1914,8 +1914,6 @@
 
   base::trace_event::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_);
 
-  if (auto* factory = AudioOutputIPCFactory::get())
-    factory->MaybeDeregisterRemoteFactory(GetRoutingID());
 
   if (is_main_frame_) {
     // Ensure the RenderView doesn't point to this object, once it is destroyed.
@@ -1957,7 +1955,8 @@
 
   // AudioOutputIPCFactory may be null in tests.
   if (auto* factory = AudioOutputIPCFactory::get())
-    factory->RegisterRemoteFactory(GetRoutingID(), GetBrowserInterfaceBroker());
+    factory->RegisterRemoteFactory(GetWebFrame()->GetFrameToken(),
+                                   GetBrowserInterfaceBroker());
 
   AudioRendererSinkCache::ObserveFrame(this);
 
@@ -4001,6 +4000,9 @@
   for (auto& observer : observers_)
     observer.FrameDetached();
 
+  if (auto* factory = AudioOutputIPCFactory::get())
+    factory->MaybeDeregisterRemoteFactory(GetWebFrame()->GetFrameToken());
+
   // Send a state update before the frame is detached.
   SendUpdateState();
 
@@ -4238,8 +4240,8 @@
       // TODO(https://crbug.com/668275): Still, it is odd for one specific
       // factory to be registered here, make this a RenderFrameObserver.
       // code.
-      factory->MaybeDeregisterRemoteFactory(GetRoutingID());
-      factory->RegisterRemoteFactory(GetRoutingID(),
+      factory->MaybeDeregisterRemoteFactory(GetWebFrame()->GetFrameToken());
+      factory->RegisterRemoteFactory(GetWebFrame()->GetFrameToken(),
                                      GetBrowserInterfaceBroker());
     }
 
@@ -6255,8 +6257,9 @@
   std::move(
       blink::ConvertToOutputDeviceStatusCB(std::move(completion_callback)))
       .Run(AudioDeviceFactory::GetOutputDeviceInfo(
-               GetRoutingID(), media::AudioSinkParameters(
-                                   base::UnguessableToken(), sink_id.Utf8()))
+               GetWebFrame()->GetFrameToken(),
+               media::AudioSinkParameters(base::UnguessableToken(),
+                                          sink_id.Utf8()))
                .device_status());
 }
 
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index f74d5d12..660a36f 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -129,8 +129,9 @@
   if (!render_frame)
     return media::AudioParameters::UnavailableDeviceParams();
 
-  return AudioDeviceFactory::GetOutputDeviceInfo(render_frame->GetRoutingID(),
-                                                 media::AudioSinkParameters())
+  return AudioDeviceFactory::GetOutputDeviceInfo(
+             render_frame->GetWebFrame()->GetFrameToken(),
+             media::AudioSinkParameters())
       .output_params();
 }
 
@@ -490,8 +491,8 @@
 RendererBlinkPlatformImpl::NewAudioCapturerSource(
     blink::WebLocalFrame* web_frame,
     const media::AudioSourceParameters& params) {
-  return AudioDeviceFactory::NewAudioCapturerSource(
-      RenderFrame::GetRoutingIdForWebFrame(web_frame), params);
+  return AudioDeviceFactory::NewAudioCapturerSource(web_frame->GetFrameToken(),
+                                                    params);
 }
 
 viz::RasterContextProvider*
@@ -525,7 +526,7 @@
     blink::WebLocalFrame* web_frame,
     const media::AudioSinkParameters& params) {
   return AudioDeviceFactory::NewAudioRendererSink(
-      source_type, RenderFrame::GetRoutingIdForWebFrame(web_frame), params);
+      source_type, web_frame->GetFrameToken(), params);
 }
 
 media::AudioLatency::LatencyType
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.cc b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
index 0f70621..948183e 100644
--- a/content/shell/renderer/web_test/web_test_content_renderer_client.cc
+++ b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
@@ -30,7 +30,6 @@
 #include "third_party/blink/public/platform/web_audio_latency_hint.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/public/web/blink.h"
-#include "third_party/blink/public/web/modules/mediastream/web_media_stream_renderer_factory.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
 #include "third_party/blink/public/web/web_testing_support.h"
 #include "ui/gfx/icc_profile.h"
diff --git a/extensions/browser/api/networking_private/networking_cast_private_delegate.h b/extensions/browser/api/networking_private/networking_cast_private_delegate.h
index 01dbd034..01c5a26 100644
--- a/extensions/browser/api/networking_private/networking_cast_private_delegate.h
+++ b/extensions/browser/api/networking_private/networking_cast_private_delegate.h
@@ -27,9 +27,10 @@
  public:
   virtual ~NetworkingCastPrivateDelegate() {}
 
-  using FailureCallback = base::Callback<void(const std::string& error)>;
-  using VerifiedCallback = base::Callback<void(bool is_valid)>;
-  using DataCallback = base::Callback<void(const std::string& encrypted_data)>;
+  using FailureCallback = base::OnceCallback<void(const std::string& error)>;
+  using VerifiedCallback = base::OnceCallback<void(bool is_valid)>;
+  using DataCallback =
+      base::OnceCallback<void(const std::string& encrypted_data)>;
 
   // API independent wrapper around cast device verification properties.
   class Credentials {
@@ -67,17 +68,16 @@
 
   // Verifies that data provided in |credentials| authenticates a cast device.
   virtual void VerifyDestination(std::unique_ptr<Credentials> credentials,
-                                 const VerifiedCallback& success_callback,
-                                 const FailureCallback& failure_callback) = 0;
+                                 VerifiedCallback success_callback,
+                                 FailureCallback failure_callback) = 0;
 
   // Verifies that data provided in |credentials| authenticates a cast device.
   // If the device is verified as a cast device, it returns |data| encrypted
   // with a public key derived from |credentials|.
-  virtual void VerifyAndEncryptData(
-      const std::string& data,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& enrypted_data_callback,
-      const FailureCallback& failure_callback) = 0;
+  virtual void VerifyAndEncryptData(const std::string& data,
+                                    std::unique_ptr<Credentials> credentials,
+                                    DataCallback enrypted_data_callback,
+                                    FailureCallback failure_callback) = 0;
 };
 
 }  // namespace extensions
diff --git a/extensions/browser/api/networking_private/networking_private_api.cc b/extensions/browser/api/networking_private/networking_private_api.cc
index 38410b8..998fbee 100644
--- a/extensions/browser/api/networking_private/networking_private_api.cc
+++ b/extensions/browser/api/networking_private/networking_private_api.cc
@@ -157,7 +157,8 @@
   GetDelegate(browser_context())
       ->GetProperties(
           params->network_guid,
-          base::Bind(&NetworkingPrivateGetPropertiesFunction::Result, this));
+          base::BindOnce(&NetworkingPrivateGetPropertiesFunction::Result,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -192,8 +193,8 @@
   GetDelegate(browser_context())
       ->GetManagedProperties(
           params->network_guid,
-          base::Bind(&NetworkingPrivateGetManagedPropertiesFunction::Result,
-                     this));
+          base::BindOnce(&NetworkingPrivateGetManagedPropertiesFunction::Result,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -224,9 +225,10 @@
   EXTENSION_FUNCTION_VALIDATE(params);
 
   GetDelegate(browser_context())
-      ->GetState(params->network_guid,
-                 base::Bind(&NetworkingPrivateGetStateFunction::Success, this),
-                 base::Bind(&NetworkingPrivateGetStateFunction::Failure, this));
+      ->GetState(
+          params->network_guid,
+          base::BindOnce(&NetworkingPrivateGetStateFunction::Success, this),
+          base::BindOnce(&NetworkingPrivateGetStateFunction::Failure, this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -270,8 +272,10 @@
       ->SetProperties(
           params->network_guid, std::move(properties_dict),
           CanChangeSharedConfig(extension(), source_context_type()),
-          base::Bind(&NetworkingPrivateSetPropertiesFunction::Success, this),
-          base::Bind(&NetworkingPrivateSetPropertiesFunction::Failure, this));
+          base::BindOnce(&NetworkingPrivateSetPropertiesFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateSetPropertiesFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -316,8 +320,10 @@
   GetDelegate(browser_context())
       ->CreateNetwork(
           params->shared, std::move(properties_dict),
-          base::Bind(&NetworkingPrivateCreateNetworkFunction::Success, this),
-          base::Bind(&NetworkingPrivateCreateNetworkFunction::Failure, this));
+          base::BindOnce(&NetworkingPrivateCreateNetworkFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateCreateNetworkFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -349,8 +355,10 @@
       ->ForgetNetwork(
           params->network_guid,
           CanChangeSharedConfig(extension(), source_context_type()),
-          base::Bind(&NetworkingPrivateForgetNetworkFunction::Success, this),
-          base::Bind(&NetworkingPrivateForgetNetworkFunction::Failure, this));
+          base::BindOnce(&NetworkingPrivateForgetNetworkFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateForgetNetworkFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -387,8 +395,8 @@
   GetDelegate(browser_context())
       ->GetNetworks(
           network_type, configured_only, visible_only, limit,
-          base::Bind(&NetworkingPrivateGetNetworksFunction::Success, this),
-          base::Bind(&NetworkingPrivateGetNetworksFunction::Failure, this));
+          base::BindOnce(&NetworkingPrivateGetNetworksFunction::Success, this),
+          base::BindOnce(&NetworkingPrivateGetNetworksFunction::Failure, this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -432,10 +440,10 @@
   GetDelegate(browser_context())
       ->GetNetworks(
           network_type, configured_only, visible_only, kDefaultNetworkListLimit,
-          base::Bind(&NetworkingPrivateGetVisibleNetworksFunction::Success,
-                     this),
-          base::Bind(&NetworkingPrivateGetVisibleNetworksFunction::Failure,
-                     this));
+          base::BindOnce(&NetworkingPrivateGetVisibleNetworksFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateGetVisibleNetworksFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -587,9 +595,9 @@
   GetDelegate(browser_context())
       ->StartConnect(
           params->network_guid,
-          base::Bind(&NetworkingPrivateStartConnectFunction::Success, this),
-          base::Bind(&NetworkingPrivateStartConnectFunction::Failure, this,
-                     params->network_guid));
+          base::BindOnce(&NetworkingPrivateStartConnectFunction::Success, this),
+          base::BindOnce(&NetworkingPrivateStartConnectFunction::Failure, this,
+                         params->network_guid));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -621,8 +629,10 @@
   GetDelegate(browser_context())
       ->StartDisconnect(
           params->network_guid,
-          base::Bind(&NetworkingPrivateStartDisconnectFunction::Success, this),
-          base::Bind(&NetworkingPrivateStartDisconnectFunction::Failure, this));
+          base::BindOnce(&NetworkingPrivateStartDisconnectFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateStartDisconnectFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -659,8 +669,10 @@
   GetDelegate(browser_context())
       ->StartActivate(
           params->network_guid, params->carrier ? *params->carrier : "",
-          base::Bind(&NetworkingPrivateStartActivateFunction::Success, this),
-          base::Bind(&NetworkingPrivateStartActivateFunction::Failure, this));
+          base::BindOnce(&NetworkingPrivateStartActivateFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateStartActivateFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -704,8 +716,10 @@
 
   delegate->VerifyDestination(
       AsCastCredentials(params->properties),
-      base::Bind(&NetworkingPrivateVerifyDestinationFunction::Success, this),
-      base::Bind(&NetworkingPrivateVerifyDestinationFunction::Failure, this));
+      base::BindOnce(&NetworkingPrivateVerifyDestinationFunction::Success,
+                     this),
+      base::BindOnce(&NetworkingPrivateVerifyDestinationFunction::Failure,
+                     this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -750,9 +764,10 @@
 
   delegate->VerifyAndEncryptData(
       params->data, AsCastCredentials(params->properties),
-      base::Bind(&NetworkingPrivateVerifyAndEncryptDataFunction::Success, this),
-      base::Bind(&NetworkingPrivateVerifyAndEncryptDataFunction::Failure,
-                 this));
+      base::BindOnce(&NetworkingPrivateVerifyAndEncryptDataFunction::Success,
+                     this),
+      base::BindOnce(&NetworkingPrivateVerifyAndEncryptDataFunction::Failure,
+                     this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -810,10 +825,10 @@
   GetDelegate(browser_context())
       ->GetCaptivePortalStatus(
           params->network_guid,
-          base::Bind(&NetworkingPrivateGetCaptivePortalStatusFunction::Success,
-                     this),
-          base::Bind(&NetworkingPrivateGetCaptivePortalStatusFunction::Failure,
-                     this));
+          base::BindOnce(
+              &NetworkingPrivateGetCaptivePortalStatusFunction::Success, this),
+          base::BindOnce(
+              &NetworkingPrivateGetCaptivePortalStatusFunction::Failure, this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -851,10 +866,10 @@
   GetDelegate(browser_context())
       ->UnlockCellularSim(
           params->network_guid, params->pin, params->puk ? *params->puk : "",
-          base::Bind(&NetworkingPrivateUnlockCellularSimFunction::Success,
-                     this),
-          base::Bind(&NetworkingPrivateUnlockCellularSimFunction::Failure,
-                     this));
+          base::BindOnce(&NetworkingPrivateUnlockCellularSimFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateUnlockCellularSimFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -892,10 +907,10 @@
           params->network_guid, params->sim_state.require_pin,
           params->sim_state.current_pin,
           params->sim_state.new_pin ? *params->sim_state.new_pin : "",
-          base::Bind(&NetworkingPrivateSetCellularSimStateFunction::Success,
-                     this),
-          base::Bind(&NetworkingPrivateSetCellularSimStateFunction::Failure,
-                     this));
+          base::BindOnce(&NetworkingPrivateSetCellularSimStateFunction::Success,
+                         this),
+          base::BindOnce(&NetworkingPrivateSetCellularSimStateFunction::Failure,
+                         this));
   // Success() or Failure() might have been called synchronously at this point.
   // In that case this function has already called Respond(). Return
   // AlreadyResponded() in that case.
@@ -931,10 +946,10 @@
   GetDelegate(browser_context())
       ->SelectCellularMobileNetwork(
           params->network_guid, params->network_id,
-          base::Bind(
+          base::BindOnce(
               &NetworkingPrivateSelectCellularMobileNetworkFunction::Success,
               this),
-          base::Bind(
+          base::BindOnce(
               &NetworkingPrivateSelectCellularMobileNetworkFunction::Failure,
               this));
   // Success() or Failure() might have been called synchronously at this point.
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc
index 07d6448..805d296a 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -165,10 +165,10 @@
 }
 
 void NetworkHandlerFailureCallback(
-    const NetworkingPrivateDelegate::FailureCallback& callback,
+    NetworkingPrivateDelegate::FailureCallback callback,
     const std::string& error_name,
     std::unique_ptr<base::DictionaryValue> error_data) {
-  callback.Run(error_name);
+  std::move(callback).Run(error_name);
 }
 
 // Returns the string corresponding to |key|. If the property is a managed
@@ -292,13 +292,12 @@
                      std::move(callback)));
 }
 
-void NetworkingPrivateChromeOS::GetState(
-    const std::string& guid,
-    const DictionaryCallback& success_callback,
-    const FailureCallback& failure_callback) {
+void NetworkingPrivateChromeOS::GetState(const std::string& guid,
+                                         DictionaryCallback success_callback,
+                                         FailureCallback failure_callback) {
   std::string service_path, error;
   if (!GetServicePathFromGuid(guid, &service_path, &error)) {
-    failure_callback.Run(error);
+    std::move(failure_callback).Run(error);
     return;
   }
 
@@ -306,7 +305,8 @@
       GetStateHandler()->GetNetworkStateFromServicePath(
           service_path, false /* configured_only */);
   if (!network_state) {
-    failure_callback.Run(networking_private::kErrorNetworkUnavailable);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorNetworkUnavailable);
     return;
   }
 
@@ -314,30 +314,31 @@
       chromeos::network_util::TranslateNetworkStateToONC(network_state);
   AppendThirdPartyProviderName(network_properties.get());
 
-  success_callback.Run(std::move(network_properties));
+  std::move(success_callback).Run(std::move(network_properties));
 }
 
 void NetworkingPrivateChromeOS::SetProperties(
     const std::string& guid,
     std::unique_ptr<base::DictionaryValue> properties,
     bool allow_set_shared_config,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   const chromeos::NetworkState* network =
       GetStateHandler()->GetNetworkStateFromGuid(guid);
   if (!network) {
-    failure_callback.Run(
-        extensions::networking_private::kErrorInvalidNetworkGuid);
+    std::move(failure_callback)
+        .Run(extensions::networking_private::kErrorInvalidNetworkGuid);
     return;
   }
   if (network->profile_path().empty()) {
-    failure_callback.Run(
-        extensions::networking_private::kErrorUnconfiguredNetwork);
+    std::move(failure_callback)
+        .Run(extensions::networking_private::kErrorUnconfiguredNetwork);
     return;
   }
   if (IsSharedNetwork(network->path())) {
     if (!allow_set_shared_config) {
-      failure_callback.Run(networking_private::kErrorAccessToSharedConfig);
+      std::move(failure_callback)
+          .Run(networking_private::kErrorAccessToSharedConfig);
       return;
     }
   } else {
@@ -345,7 +346,7 @@
     std::string error;
     // Do not allow changing a non-shared network from a secondary users.
     if (!GetPrimaryUserIdHash(browser_context_, &user_id_hash, &error)) {
-      failure_callback.Run(error);
+      std::move(failure_callback).Run(error);
       return;
     }
   }
@@ -353,27 +354,28 @@
   NET_LOG(USER) << "networkingPrivate.setProperties for: "
                 << NetworkId(network);
   GetManagedConfigurationHandler()->SetProperties(
-      network->path(), *properties, success_callback,
-      base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+      network->path(), *properties, std::move(success_callback),
+      base::BindOnce(&NetworkHandlerFailureCallback,
+                     std::move(failure_callback)));
 }
 
 void NetworkHandlerCreateCallback(
-    const NetworkingPrivateDelegate::StringCallback& callback,
+    NetworkingPrivateDelegate::StringCallback callback,
     const std::string& service_path,
     const std::string& guid) {
-  callback.Run(guid);
+  std::move(callback).Run(guid);
 }
 
 void NetworkingPrivateChromeOS::CreateNetwork(
     bool shared,
     std::unique_ptr<base::DictionaryValue> properties,
-    const StringCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    StringCallback success_callback,
+    FailureCallback failure_callback) {
   std::string user_id_hash, error;
   // Do not allow configuring a non-shared network from a non-primary user.
   if (!shared &&
       !GetPrimaryUserIdHash(browser_context_, &user_id_hash, &error)) {
-    failure_callback.Run(error);
+    std::move(failure_callback).Run(error);
     return;
   }
 
@@ -382,18 +384,20 @@
   NET_LOG(USER) << "networkingPrivate.CreateNetwork. GUID=" << guid;
   GetManagedConfigurationHandler()->CreateConfiguration(
       user_id_hash, *properties,
-      base::Bind(&NetworkHandlerCreateCallback, success_callback),
-      base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+      base::BindOnce(&NetworkHandlerCreateCallback,
+                     std::move(success_callback)),
+      base::BindOnce(&NetworkHandlerFailureCallback,
+                     std::move(failure_callback)));
 }
 
 void NetworkingPrivateChromeOS::ForgetNetwork(
     const std::string& guid,
     bool allow_forget_shared_config,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   std::string service_path, error;
   if (!GetServicePathFromGuid(guid, &service_path, &error)) {
-    failure_callback.Run(error);
+    std::move(failure_callback).Run(error);
     return;
   }
 
@@ -401,7 +405,8 @@
       GetStateHandler()->GetNetworkStateFromServicePath(
           service_path, true /* configured only */);
   if (!network) {
-    failure_callback.Run(networking_private::kErrorNetworkUnavailable);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorNetworkUnavailable);
     return;
   }
 
@@ -411,12 +416,13 @@
   // never get loaded by shill).
   if (!GetPrimaryUserIdHash(browser_context_, &user_id_hash, &error) &&
       network->IsPrivate()) {
-    failure_callback.Run(error);
+    std::move(failure_callback).Run(error);
     return;
   }
 
   if (!allow_forget_shared_config && !network->IsPrivate()) {
-    failure_callback.Run(networking_private::kErrorAccessToSharedConfig);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorAccessToSharedConfig);
     return;
   }
 
@@ -427,19 +433,22 @@
     if (onc_source == onc::ONC_SOURCE_DEVICE_POLICY) {
       allow_forget_shared_config = false;
     } else {
-      failure_callback.Run(networking_private::kErrorPolicyControlled);
+      std::move(failure_callback)
+          .Run(networking_private::kErrorPolicyControlled);
       return;
     }
   }
 
   if (allow_forget_shared_config) {
     GetManagedConfigurationHandler()->RemoveConfiguration(
-        service_path, success_callback,
-        base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+        service_path, std::move(success_callback),
+        base::BindOnce(&NetworkHandlerFailureCallback,
+                       std::move(failure_callback)));
   } else {
     GetManagedConfigurationHandler()->RemoveConfigurationFromCurrentProfile(
-        service_path, success_callback,
-        base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+        service_path, std::move(success_callback),
+        base::BindOnce(&NetworkHandlerFailureCallback,
+                       std::move(failure_callback)));
   }
 }
 
@@ -448,8 +457,8 @@
     bool configured_only,
     bool visible_only,
     int limit,
-    const NetworkListCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    NetworkListCallback success_callback,
+    FailureCallback failure_callback) {
   // When requesting configured Ethernet networks, include EthernetEAP.
   NetworkTypePattern pattern =
       (!visible_only && network_type == ::onc::network_type::kEthernet)
@@ -467,69 +476,70 @@
       AppendThirdPartyProviderName(network_dict);
   }
 
-  success_callback.Run(std::move(network_properties_list));
+  std::move(success_callback).Run(std::move(network_properties_list));
 }
 
-void NetworkingPrivateChromeOS::StartConnect(
-    const std::string& guid,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+void NetworkingPrivateChromeOS::StartConnect(const std::string& guid,
+                                             VoidCallback success_callback,
+                                             FailureCallback failure_callback) {
   std::string service_path, error;
   if (!GetServicePathFromGuid(guid, &service_path, &error)) {
-    failure_callback.Run(error);
+    std::move(failure_callback).Run(error);
     return;
   }
 
   NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
-      service_path, success_callback,
-      base::Bind(&NetworkHandlerFailureCallback, failure_callback),
+      service_path, std::move(success_callback),
+      base::BindOnce(&NetworkHandlerFailureCallback,
+                     std::move(failure_callback)),
       true /* check_error_state */, chromeos::ConnectCallbackMode::ON_STARTED);
 }
 
 void NetworkingPrivateChromeOS::StartDisconnect(
     const std::string& guid,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   std::string service_path, error;
   if (!GetServicePathFromGuid(guid, &service_path, &error)) {
-    failure_callback.Run(error);
+    std::move(failure_callback).Run(error);
     return;
   }
 
   NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
-      service_path, success_callback,
-      base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+      service_path, std::move(success_callback),
+      base::BindOnce(&NetworkHandlerFailureCallback,
+                     std::move(failure_callback)));
 }
 
 void NetworkingPrivateChromeOS::StartActivate(
     const std::string& guid,
     const std::string& specified_carrier,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   const chromeos::NetworkState* network =
       GetStateHandler()->GetNetworkStateFromGuid(guid);
   if (!network) {
-    failure_callback.Run(
-        extensions::networking_private::kErrorInvalidNetworkGuid);
+    std::move(failure_callback)
+        .Run(extensions::networking_private::kErrorInvalidNetworkGuid);
     return;
   }
 
   if (ui_delegate())
     ui_delegate()->ShowAccountDetails(guid);
-  success_callback.Run();
+  std::move(success_callback).Run();
 }
 
 void NetworkingPrivateChromeOS::GetCaptivePortalStatus(
     const std::string& guid,
-    const StringCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    StringCallback success_callback,
+    FailureCallback failure_callback) {
   if (!chromeos::network_portal_detector::IsInitialized()) {
-    failure_callback.Run(networking_private::kErrorNotReady);
+    std::move(failure_callback).Run(networking_private::kErrorNotReady);
     return;
   }
 
-  success_callback.Run(
-      chromeos::NetworkPortalDetector::CaptivePortalStatusString(
+  std::move(success_callback)
+      .Run(chromeos::NetworkPortalDetector::CaptivePortalStatusString(
           chromeos::network_portal_detector::GetInstance()
               ->GetCaptivePortalState(guid)
               .status));
@@ -539,29 +549,33 @@
     const std::string& guid,
     const std::string& pin,
     const std::string& puk,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   const chromeos::DeviceState* device_state = GetCellularDeviceState(guid);
   if (!device_state) {
-    failure_callback.Run(networking_private::kErrorNetworkUnavailable);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorNetworkUnavailable);
     return;
   }
   std::string lock_type = device_state->sim_lock_type();
   if (lock_type.empty()) {
     // Sim is already unlocked.
-    failure_callback.Run(networking_private::kErrorInvalidNetworkOperation);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorInvalidNetworkOperation);
     return;
   }
 
   // Unblock or unlock the SIM.
   if (lock_type == shill::kSIMLockPuk) {
     NetworkHandler::Get()->network_device_handler()->UnblockPin(
-        device_state->path(), puk, pin, success_callback,
-        base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+        device_state->path(), puk, pin, std::move(success_callback),
+        base::BindOnce(&NetworkHandlerFailureCallback,
+                       std::move(failure_callback)));
   } else {
     NetworkHandler::Get()->network_device_handler()->EnterPin(
-        device_state->path(), pin, success_callback,
-        base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+        device_state->path(), pin, std::move(success_callback),
+        base::BindOnce(&NetworkHandlerFailureCallback,
+                       std::move(failure_callback)));
   }
 }
 
@@ -570,16 +584,17 @@
     bool require_pin,
     const std::string& current_pin,
     const std::string& new_pin,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   const chromeos::DeviceState* device_state = GetCellularDeviceState(guid);
   if (!device_state) {
-    failure_callback.Run(networking_private::kErrorNetworkUnavailable);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorNetworkUnavailable);
     return;
   }
   if (!device_state->sim_lock_type().empty()) {
     // The SIM needs to be unlocked before the state can be changed.
-    failure_callback.Run(networking_private::kErrorSimLocked);
+    std::move(failure_callback).Run(networking_private::kErrorSimLocked);
     return;
   }
 
@@ -591,8 +606,10 @@
   // disable (require_pin == false) SIM locking.
   if (new_pin.empty()) {
     NetworkHandler::Get()->network_device_handler()->RequirePin(
-        device_state->path(), require_pin, current_pin, success_callback,
-        base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+        device_state->path(), require_pin, current_pin,
+        std::move(success_callback),
+        base::BindOnce(&NetworkHandlerFailureCallback,
+                       std::move(failure_callback)));
     return;
   }
 
@@ -600,28 +617,31 @@
   // |new_pin|, which also requires SIM locking to be enabled, i.e.
   // require_pin == true.
   if (!require_pin) {
-    failure_callback.Run(networking_private::kErrorInvalidArguments);
+    std::move(failure_callback).Run(networking_private::kErrorInvalidArguments);
     return;
   }
 
   NetworkHandler::Get()->network_device_handler()->ChangePin(
-      device_state->path(), current_pin, new_pin, success_callback,
-      base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+      device_state->path(), current_pin, new_pin, std::move(success_callback),
+      base::BindOnce(&NetworkHandlerFailureCallback,
+                     std::move(failure_callback)));
 }
 
 void NetworkingPrivateChromeOS::SelectCellularMobileNetwork(
     const std::string& guid,
     const std::string& network_id,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   const chromeos::DeviceState* device_state = GetCellularDeviceState(guid);
   if (!device_state) {
-    failure_callback.Run(networking_private::kErrorNetworkUnavailable);
+    std::move(failure_callback)
+        .Run(networking_private::kErrorNetworkUnavailable);
     return;
   }
   NetworkHandler::Get()->network_device_handler()->RegisterCellularNetwork(
-      device_state->path(), network_id, success_callback,
-      base::Bind(&NetworkHandlerFailureCallback, failure_callback));
+      device_state->path(), network_id, std::move(success_callback),
+      base::BindOnce(&NetworkHandlerFailureCallback,
+                     std::move(failure_callback)));
 }
 
 std::unique_ptr<base::ListValue>
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.h b/extensions/browser/api/networking_private/networking_private_chromeos.h
index 33e87c27..9692cf06 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos.h
+++ b/extensions/browser/api/networking_private/networking_private_chromeos.h
@@ -34,56 +34,55 @@
   void GetManagedProperties(const std::string& guid,
                             PropertiesCallback callback) override;
   void GetState(const std::string& guid,
-                const DictionaryCallback& success_callback,
-                const FailureCallback& failure_callback) override;
+                DictionaryCallback success_callback,
+                FailureCallback failure_callback) override;
   void SetProperties(const std::string& guid,
                      std::unique_ptr<base::DictionaryValue> properties,
                      bool allow_set_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void CreateNetwork(bool shared,
                      std::unique_ptr<base::DictionaryValue> properties,
-                     const StringCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     StringCallback success_callback,
+                     FailureCallback failure_callback) override;
   void ForgetNetwork(const std::string& guid,
                      bool allow_forget_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void GetNetworks(const std::string& network_type,
                    bool configured_only,
                    bool visible_only,
                    int limit,
-                   const NetworkListCallback& success_callback,
-                   const FailureCallback& failure_callback) override;
+                   NetworkListCallback success_callback,
+                   FailureCallback failure_callback) override;
   void StartConnect(const std::string& guid,
-                    const VoidCallback& success_callback,
-                    const FailureCallback& failure_callback) override;
+                    VoidCallback success_callback,
+                    FailureCallback failure_callback) override;
   void StartDisconnect(const std::string& guid,
-                       const VoidCallback& success_callback,
-                       const FailureCallback& failure_callback) override;
+                       VoidCallback success_callback,
+                       FailureCallback failure_callback) override;
   void StartActivate(const std::string& guid,
                      const std::string& carrier,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void GetCaptivePortalStatus(const std::string& guid,
-                              const StringCallback& success_callback,
-                              const FailureCallback& failure_callback) override;
+                              StringCallback success_callback,
+                              FailureCallback failure_callback) override;
   void UnlockCellularSim(const std::string& guid,
                          const std::string& pin,
                          const std::string& puk,
-                         const VoidCallback& success_callback,
-                         const FailureCallback& failure_callback) override;
+                         VoidCallback success_callback,
+                         FailureCallback failure_callback) override;
   void SetCellularSimState(const std::string& guid,
                            bool require_pin,
                            const std::string& current_pin,
                            const std::string& new_pin,
-                           const VoidCallback& success_callback,
-                           const FailureCallback& failure_callback) override;
-  void SelectCellularMobileNetwork(
-      const std::string& guid,
-      const std::string& network_id,
-      const VoidCallback& success_callback,
-      const FailureCallback& failure_callback) override;
+                           VoidCallback success_callback,
+                           FailureCallback failure_callback) override;
+  void SelectCellularMobileNetwork(const std::string& guid,
+                                   const std::string& network_id,
+                                   VoidCallback success_callback,
+                                   FailureCallback failure_callback) override;
   std::unique_ptr<base::ListValue> GetEnabledNetworkTypes() override;
   std::unique_ptr<DeviceStateList> GetDeviceStateList() override;
   std::unique_ptr<base::DictionaryValue> GetGlobalPolicy() override;
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc b/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
index e60703aa..3088ee89 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
@@ -301,17 +301,17 @@
 
   void OnNetworkProperties(const std::string& expected_path,
                            base::Optional<base::Value>* result,
-                           const base::Closure& callback,
+                           base::OnceClosure callback,
                            const std::string& service_path,
                            base::Optional<base::Value> properties) {
     if (!properties) {
       ADD_FAILURE() << "Error calling shill client.";
-      callback.Run();
+      std::move(callback).Run();
       return;
     }
     EXPECT_EQ(expected_path, service_path);
     *result = std::move(properties);
-    callback.Run();
+    std::move(callback).Run();
   }
 
   std::unique_ptr<base::DictionaryValue> GetNetworkUiData(
diff --git a/extensions/browser/api/networking_private/networking_private_delegate.cc b/extensions/browser/api/networking_private/networking_private_delegate.cc
index a6f12ea..e9f6287 100644
--- a/extensions/browser/api/networking_private/networking_private_delegate.cc
+++ b/extensions/browser/api/networking_private/networking_private_delegate.cc
@@ -30,9 +30,9 @@
 void NetworkingPrivateDelegate::StartActivate(
     const std::string& guid,
     const std::string& carrier,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  failure_callback.Run(networking_private::kErrorNotSupported);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  std::move(failure_callback).Run(networking_private::kErrorNotSupported);
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/api/networking_private/networking_private_delegate.h b/extensions/browser/api/networking_private/networking_private_delegate.h
index 62dac59..33972c5 100644
--- a/extensions/browser/api/networking_private/networking_private_delegate.h
+++ b/extensions/browser/api/networking_private/networking_private_delegate.h
@@ -26,13 +26,13 @@
 class NetworkingPrivateDelegate : public KeyedService {
  public:
   using DictionaryCallback =
-      base::Callback<void(std::unique_ptr<base::DictionaryValue>)>;
-  using VoidCallback = base::Callback<void()>;
-  using BoolCallback = base::Callback<void(bool)>;
-  using StringCallback = base::Callback<void(const std::string&)>;
+      base::OnceCallback<void(std::unique_ptr<base::DictionaryValue>)>;
+  using VoidCallback = base::OnceCallback<void()>;
+  using BoolCallback = base::OnceCallback<void(bool)>;
+  using StringCallback = base::OnceCallback<void(const std::string&)>;
   using NetworkListCallback =
-      base::Callback<void(std::unique_ptr<base::ListValue>)>;
-  using FailureCallback = base::Callback<void(const std::string&)>;
+      base::OnceCallback<void(std::unique_ptr<base::ListValue>)>;
+  using FailureCallback = base::OnceCallback<void(const std::string&)>;
   using DeviceStateList = std::vector<
       std::unique_ptr<api::networking_private::DeviceStateProperties>>;
 
@@ -70,57 +70,56 @@
   virtual void GetManagedProperties(const std::string& guid,
                                     PropertiesCallback callback) = 0;
   virtual void GetState(const std::string& guid,
-                        const DictionaryCallback& success_callback,
-                        const FailureCallback& failure_callback) = 0;
+                        DictionaryCallback success_callback,
+                        FailureCallback failure_callback) = 0;
   virtual void SetProperties(const std::string& guid,
                              std::unique_ptr<base::DictionaryValue> properties,
                              bool allow_set_shared_config,
-                             const VoidCallback& success_callback,
-                             const FailureCallback& failure_callback) = 0;
+                             VoidCallback success_callback,
+                             FailureCallback failure_callback) = 0;
   virtual void CreateNetwork(bool shared,
                              std::unique_ptr<base::DictionaryValue> properties,
-                             const StringCallback& success_callback,
-                             const FailureCallback& failure_callback) = 0;
+                             StringCallback success_callback,
+                             FailureCallback failure_callback) = 0;
   virtual void ForgetNetwork(const std::string& guid,
                              bool allow_forget_shared_config,
-                             const VoidCallback& success_callback,
-                             const FailureCallback& failure_callback) = 0;
+                             VoidCallback success_callback,
+                             FailureCallback failure_callback) = 0;
   virtual void GetNetworks(const std::string& network_type,
                            bool configured_only,
                            bool visible_only,
                            int limit,
-                           const NetworkListCallback& success_callback,
-                           const FailureCallback& failure_callback) = 0;
+                           NetworkListCallback success_callback,
+                           FailureCallback failure_callback) = 0;
   virtual void StartConnect(const std::string& guid,
-                            const VoidCallback& success_callback,
-                            const FailureCallback& failure_callback) = 0;
+                            VoidCallback success_callback,
+                            FailureCallback failure_callback) = 0;
   virtual void StartDisconnect(const std::string& guid,
-                               const VoidCallback& success_callback,
-                               const FailureCallback& failure_callback) = 0;
+                               VoidCallback success_callback,
+                               FailureCallback failure_callback) = 0;
   virtual void StartActivate(const std::string& guid,
                              const std::string& carrier,
-                             const VoidCallback& success_callback,
-                             const FailureCallback& failure_callback);
-  virtual void GetCaptivePortalStatus(
-      const std::string& guid,
-      const StringCallback& success_callback,
-      const FailureCallback& failure_callback) = 0;
+                             VoidCallback success_callback,
+                             FailureCallback failure_callback);
+  virtual void GetCaptivePortalStatus(const std::string& guid,
+                                      StringCallback success_callback,
+                                      FailureCallback failure_callback) = 0;
   virtual void UnlockCellularSim(const std::string& guid,
                                  const std::string& pin,
                                  const std::string& puk,
-                                 const VoidCallback& success_callback,
-                                 const FailureCallback& failure_callback) = 0;
+                                 VoidCallback success_callback,
+                                 FailureCallback failure_callback) = 0;
   virtual void SetCellularSimState(const std::string& guid,
                                    bool require_pin,
                                    const std::string& current_pin,
                                    const std::string& new_pin,
-                                   const VoidCallback& success_callback,
-                                   const FailureCallback& failure_callback) = 0;
+                                   VoidCallback success_callback,
+                                   FailureCallback failure_callback) = 0;
   virtual void SelectCellularMobileNetwork(
       const std::string& guid,
       const std::string& network_id,
-      const VoidCallback& success_callback,
-      const FailureCallback& failure_callback) = 0;
+      VoidCallback success_callback,
+      FailureCallback failure_callback) = 0;
 
   // Synchronous methods
 
diff --git a/extensions/browser/api/networking_private/networking_private_linux.cc b/extensions/browser/api/networking_private/networking_private_linux.cc
index 1c4712f..0bbfc2c 100644
--- a/extensions/browser/api/networking_private/networking_private_linux.cc
+++ b/extensions/browser/api/networking_private/networking_private_linux.cc
@@ -100,22 +100,23 @@
 // to the failure callback.
 void ReportNotSupported(
     const std::string& method_name,
-    const NetworkingPrivateDelegate::FailureCallback& failure_callback) {
+    NetworkingPrivateDelegate::FailureCallback failure_callback) {
   LOG(WARNING) << method_name << " is not supported";
-  failure_callback.Run(extensions::networking_private::kErrorNotSupported);
+  std::move(failure_callback)
+      .Run(extensions::networking_private::kErrorNotSupported);
 }
 
 // Fires the appropriate callback when the network connect operation succeeds
 // or fails.
 void OnNetworkConnectOperationCompleted(
     std::unique_ptr<std::string> error,
-    const NetworkingPrivateDelegate::VoidCallback& success_callback,
-    const NetworkingPrivateDelegate::FailureCallback& failure_callback) {
+    NetworkingPrivateDelegate::VoidCallback success_callback,
+    NetworkingPrivateDelegate::FailureCallback failure_callback) {
   if (!error->empty()) {
-    failure_callback.Run(*error);
+    std::move(failure_callback).Run(*error);
     return;
   }
-  success_callback.Run();
+  std::move(success_callback).Run();
 }
 
 // Fires the appropriate callback when the network properties are returned
@@ -123,13 +124,13 @@
 void GetCachedNetworkPropertiesCallback(
     std::unique_ptr<std::string> error,
     std::unique_ptr<base::DictionaryValue> properties,
-    const NetworkingPrivateDelegate::DictionaryCallback& success_callback,
-    const NetworkingPrivateDelegate::FailureCallback& failure_callback) {
+    NetworkingPrivateDelegate::DictionaryCallback success_callback,
+    NetworkingPrivateDelegate::FailureCallback failure_callback) {
   if (!error->empty()) {
-    failure_callback.Run(*error);
+    std::move(failure_callback).Run(*error);
     return;
   }
-  success_callback.Run(std::move(properties));
+  std::move(success_callback).Run(std::move(properties));
 }
 
 // Fires the appropriate callback when the network properties are returned
@@ -193,14 +194,8 @@
   network_map_.reset(new NetworkMap());
 }
 
-bool NetworkingPrivateLinux::CheckNetworkManagerSupported(
-    const FailureCallback& failure_callback) {
-  if (!network_manager_proxy_) {
-    ReportNotSupported("NetworkManager over DBus", failure_callback);
-    return false;
-  }
-
-  return true;
+bool NetworkingPrivateLinux::CheckNetworkManagerSupported() {
+  return network_manager_proxy_ != nullptr;
 }
 
 void NetworkingPrivateLinux::GetProperties(const std::string& guid,
@@ -237,12 +232,13 @@
                           extensions::networking_private::kErrorNotSupported);
 }
 
-void NetworkingPrivateLinux::GetState(
-    const std::string& guid,
-    const DictionaryCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  if (!CheckNetworkManagerSupported(failure_callback))
+void NetworkingPrivateLinux::GetState(const std::string& guid,
+                                      DictionaryCallback success_callback,
+                                      FailureCallback failure_callback) {
+  if (!CheckNetworkManagerSupported()) {
+    ReportNotSupported("GetState", std::move(failure_callback));
     return;
+  }
 
   std::unique_ptr<std::string> error(new std::string);
   std::unique_ptr<base::DictionaryValue> network_properties(
@@ -258,8 +254,8 @@
                      base::Unretained(network_prop_ptr),
                      base::Unretained(error_ptr)),
       base::BindOnce(&GetCachedNetworkPropertiesCallback, base::Passed(&error),
-                     base::Passed(&network_properties), success_callback,
-                     failure_callback));
+                     base::Passed(&network_properties),
+                     std::move(success_callback), std::move(failure_callback)));
 }
 
 void NetworkingPrivateLinux::GetCachedNetworkProperties(
@@ -293,36 +289,35 @@
     const std::string& guid,
     std::unique_ptr<base::DictionaryValue> properties,
     bool allow_set_shared_config,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  ReportNotSupported("SetProperties", failure_callback);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  ReportNotSupported("SetProperties", std::move(failure_callback));
 }
 
 void NetworkingPrivateLinux::CreateNetwork(
     bool shared,
     std::unique_ptr<base::DictionaryValue> properties,
-    const StringCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  ReportNotSupported("CreateNetwork", failure_callback);
+    StringCallback success_callback,
+    FailureCallback failure_callback) {
+  ReportNotSupported("CreateNetwork", std::move(failure_callback));
 }
 
-void NetworkingPrivateLinux::ForgetNetwork(
-    const std::string& guid,
-    bool allow_forget_shared_config,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+void NetworkingPrivateLinux::ForgetNetwork(const std::string& guid,
+                                           bool allow_forget_shared_config,
+                                           VoidCallback success_callback,
+                                           FailureCallback failure_callback) {
   // TODO(zentaro): Implement for Linux.
-  ReportNotSupported("ForgetNetwork", failure_callback);
+  ReportNotSupported("ForgetNetwork", std::move(failure_callback));
 }
 
-void NetworkingPrivateLinux::GetNetworks(
-    const std::string& network_type,
-    bool configured_only,
-    bool visible_only,
-    int limit,
-    const NetworkListCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  if (!CheckNetworkManagerSupported(failure_callback)) {
+void NetworkingPrivateLinux::GetNetworks(const std::string& network_type,
+                                         bool configured_only,
+                                         bool visible_only,
+                                         int limit,
+                                         NetworkListCallback success_callback,
+                                         FailureCallback failure_callback) {
+  if (!CheckNetworkManagerSupported()) {
+    ReportNotSupported("GetNetworks", std::move(failure_callback));
     return;
   }
 
@@ -333,7 +328,7 @@
         network_type == ::onc::network_type::kAllTypes)) {
     // Only enumerating WiFi networks is supported on linux.
     ReportNotSupported("GetNetworks with network_type=" + network_type,
-                       failure_callback);
+                       std::move(failure_callback));
     return;
   }
 
@@ -347,7 +342,7 @@
                      limit, base::Unretained(network_map_ptr)),
       base::BindOnce(&NetworkingPrivateLinux::OnAccessPointsFound,
                      base::Unretained(this), base::Passed(&network_map),
-                     success_callback, failure_callback));
+                     std::move(success_callback), std::move(failure_callback)));
 }
 
 bool NetworkingPrivateLinux::GetNetworksForScanRequest() {
@@ -538,12 +533,13 @@
   }
 }
 
-void NetworkingPrivateLinux::StartConnect(
-    const std::string& guid,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  if (!CheckNetworkManagerSupported(failure_callback))
+void NetworkingPrivateLinux::StartConnect(const std::string& guid,
+                                          VoidCallback success_callback,
+                                          FailureCallback failure_callback) {
+  if (!CheckNetworkManagerSupported()) {
+    ReportNotSupported("StartConnect", std::move(failure_callback));
     return;
+  }
 
   std::unique_ptr<std::string> error(new std::string);
 
@@ -554,15 +550,16 @@
       base::BindOnce(&NetworkingPrivateLinux::ConnectToNetwork,
                      base::Unretained(this), guid, base::Unretained(error_ptr)),
       base::BindOnce(&OnNetworkConnectOperationCompleted, base::Passed(&error),
-                     success_callback, failure_callback));
+                     std::move(success_callback), std::move(failure_callback)));
 }
 
-void NetworkingPrivateLinux::StartDisconnect(
-    const std::string& guid,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  if (!CheckNetworkManagerSupported(failure_callback))
+void NetworkingPrivateLinux::StartDisconnect(const std::string& guid,
+                                             VoidCallback success_callback,
+                                             FailureCallback failure_callback) {
+  if (!CheckNetworkManagerSupported()) {
+    ReportNotSupported("StartDisconnect", std::move(failure_callback));
     return;
+  }
 
   std::unique_ptr<std::string> error(new std::string);
 
@@ -573,23 +570,23 @@
       base::BindOnce(&NetworkingPrivateLinux::DisconnectFromNetwork,
                      base::Unretained(this), guid, base::Unretained(error_ptr)),
       base::BindOnce(&OnNetworkConnectOperationCompleted, base::Passed(&error),
-                     success_callback, failure_callback));
+                     std::move(success_callback), std::move(failure_callback)));
 }
 
 void NetworkingPrivateLinux::GetCaptivePortalStatus(
     const std::string& guid,
-    const StringCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  ReportNotSupported("GetCaptivePortalStatus", failure_callback);
+    StringCallback success_callback,
+    FailureCallback failure_callback) {
+  ReportNotSupported("GetCaptivePortalStatus", std::move(failure_callback));
 }
 
 void NetworkingPrivateLinux::UnlockCellularSim(
     const std::string& guid,
     const std::string& pin,
     const std::string& puk,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  ReportNotSupported("UnlockCellularSim", failure_callback);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  ReportNotSupported("UnlockCellularSim", std::move(failure_callback));
 }
 
 void NetworkingPrivateLinux::SetCellularSimState(
@@ -597,17 +594,18 @@
     bool require_pin,
     const std::string& current_pin,
     const std::string& new_pin,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  ReportNotSupported("SetCellularSimState", failure_callback);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  ReportNotSupported("SetCellularSimState", std::move(failure_callback));
 }
 
 void NetworkingPrivateLinux::SelectCellularMobileNetwork(
     const std::string& guid,
     const std::string& network_id,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  ReportNotSupported("SelectCellularMobileNetwork", failure_callback);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  ReportNotSupported("SelectCellularMobileNetwork",
+                     std::move(failure_callback));
 }
 
 std::unique_ptr<base::ListValue>
@@ -662,14 +660,14 @@
 
 void NetworkingPrivateLinux::OnAccessPointsFound(
     std::unique_ptr<NetworkMap> network_map,
-    const NetworkListCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    NetworkListCallback success_callback,
+    FailureCallback failure_callback) {
   std::unique_ptr<base::ListValue> network_list =
       CopyNetworkMapToList(*network_map);
   // Give ownership to the member variable.
   network_map_.swap(network_map);
   SendNetworkListChangedEvent(*network_list);
-  success_callback.Run(std::move(network_list));
+  std::move(success_callback).Run(std::move(network_list));
 }
 
 void NetworkingPrivateLinux::OnAccessPointsFoundViaScan(
diff --git a/extensions/browser/api/networking_private/networking_private_linux.h b/extensions/browser/api/networking_private/networking_private_linux.h
index a677d152..81a91bd 100644
--- a/extensions/browser/api/networking_private/networking_private_linux.h
+++ b/extensions/browser/api/networking_private/networking_private_linux.h
@@ -41,52 +41,51 @@
   void GetManagedProperties(const std::string& guid,
                             PropertiesCallback callback) override;
   void GetState(const std::string& guid,
-                const DictionaryCallback& success_callback,
-                const FailureCallback& failure_callback) override;
+                DictionaryCallback success_callback,
+                FailureCallback failure_callback) override;
   void SetProperties(const std::string& guid,
                      std::unique_ptr<base::DictionaryValue> properties,
                      bool allow_set_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void CreateNetwork(bool shared,
                      std::unique_ptr<base::DictionaryValue> properties,
-                     const StringCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     StringCallback success_callback,
+                     FailureCallback failure_callback) override;
   void ForgetNetwork(const std::string& guid,
                      bool allow_forget_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void GetNetworks(const std::string& network_type,
                    bool configured_only,
                    bool visible_only,
                    int limit,
-                   const NetworkListCallback& success_callback,
-                   const FailureCallback& failure_callback) override;
+                   NetworkListCallback success_callback,
+                   FailureCallback failure_callback) override;
   void StartConnect(const std::string& guid,
-                    const VoidCallback& success_callback,
-                    const FailureCallback& failure_callback) override;
+                    VoidCallback success_callback,
+                    FailureCallback failure_callback) override;
   void StartDisconnect(const std::string& guid,
-                       const VoidCallback& success_callback,
-                       const FailureCallback& failure_callback) override;
+                       VoidCallback success_callback,
+                       FailureCallback failure_callback) override;
   void GetCaptivePortalStatus(const std::string& guid,
-                              const StringCallback& success_callback,
-                              const FailureCallback& failure_callback) override;
+                              StringCallback success_callback,
+                              FailureCallback failure_callback) override;
   void UnlockCellularSim(const std::string& guid,
                          const std::string& pin,
                          const std::string& puk,
-                         const VoidCallback& success_callback,
-                         const FailureCallback& failure_callback) override;
+                         VoidCallback success_callback,
+                         FailureCallback failure_callback) override;
   void SetCellularSimState(const std::string& guid,
                            bool require_pin,
                            const std::string& current_pin,
                            const std::string& new_pin,
-                           const VoidCallback& success_callback,
-                           const FailureCallback& failure_callback) override;
-  void SelectCellularMobileNetwork(
-      const std::string& guid,
-      const std::string& network_id,
-      const VoidCallback& success_callback,
-      const FailureCallback& failure_callback) override;
+                           VoidCallback success_callback,
+                           FailureCallback failure_callback) override;
+  void SelectCellularMobileNetwork(const std::string& guid,
+                                   const std::string& network_id,
+                                   VoidCallback success_callback,
+                                   FailureCallback failure_callback) override;
   std::unique_ptr<base::ListValue> GetEnabledNetworkTypes() override;
   std::unique_ptr<DeviceStateList> GetDeviceStateList() override;
   std::unique_ptr<base::DictionaryValue> GetGlobalPolicy() override;
@@ -154,7 +153,7 @@
   // Verifies that NetworkManager interfaces are initialized.
   // Returns true if NetworkManager is initialized, otherwise returns false
   // and the API call will fail with |kErrorNotSupported|.
-  bool CheckNetworkManagerSupported(const FailureCallback& failure_callback);
+  bool CheckNetworkManagerSupported();
 
   // Gets all network devices on the system.
   // Returns false if there is an error getting the device paths.
@@ -174,8 +173,8 @@
   // Reply callback accepts the map of networks and fires the
   // OnNetworkListChanged event and user callbacks.
   void OnAccessPointsFound(std::unique_ptr<NetworkMap> network_map,
-                           const NetworkListCallback& success_callback,
-                           const FailureCallback& failure_callback);
+                           NetworkListCallback success_callback,
+                           FailureCallback failure_callback);
 
   // Reply callback accepts the map of networks and fires the
   // OnNetworkListChanged event.
diff --git a/extensions/browser/api/networking_private/networking_private_service_client.cc b/extensions/browser/api/networking_private/networking_private_service_client.cc
index ddd8b6a8..6714784 100644
--- a/extensions/browser/api/networking_private/networking_private_service_client.cc
+++ b/extensions/browser/api/networking_private/networking_private_service_client.cc
@@ -60,12 +60,12 @@
           &WiFiService::SetEventObservers,
           base::Unretained(wifi_service_.get()),
           base::ThreadTaskRunnerHandle::Get(),
-          base::Bind(
+          base::BindRepeating(
               &NetworkingPrivateServiceClient::OnNetworksChangedEventOnUIThread,
               weak_factory_.GetWeakPtr()),
-          base::Bind(&NetworkingPrivateServiceClient::
-                         OnNetworkListChangedEventOnUIThread,
-                     weak_factory_.GetWeakPtr())));
+          base::BindRepeating(&NetworkingPrivateServiceClient::
+                                  OnNetworkListChangedEventOnUIThread,
+                              weak_factory_.GetWeakPtr())));
   content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this);
 }
 
@@ -155,11 +155,11 @@
 
 void NetworkingPrivateServiceClient::GetState(
     const std::string& guid,
-    const DictionaryCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    DictionaryCallback success_callback,
+    FailureCallback failure_callback) {
   ServiceCallbacks* service_callbacks = AddServiceCallbacks();
-  service_callbacks->failure_callback = failure_callback;
-  service_callbacks->get_properties_callback = success_callback;
+  service_callbacks->failure_callback = std::move(failure_callback);
+  service_callbacks->get_properties_callback = std::move(success_callback);
 
   std::unique_ptr<base::DictionaryValue> properties(new base::DictionaryValue);
   std::string* error = new std::string;
@@ -179,13 +179,13 @@
     const std::string& guid,
     std::unique_ptr<base::DictionaryValue> properties,
     bool allow_set_shared_config,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   CHECK(allow_set_shared_config);
 
   ServiceCallbacks* service_callbacks = AddServiceCallbacks();
-  service_callbacks->failure_callback = failure_callback;
-  service_callbacks->set_properties_callback = success_callback;
+  service_callbacks->failure_callback = std::move(failure_callback);
+  service_callbacks->set_properties_callback = std::move(success_callback);
 
   std::string* error = new std::string;
 
@@ -202,11 +202,11 @@
 void NetworkingPrivateServiceClient::CreateNetwork(
     bool shared,
     std::unique_ptr<base::DictionaryValue> properties,
-    const StringCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    StringCallback success_callback,
+    FailureCallback failure_callback) {
   ServiceCallbacks* service_callbacks = AddServiceCallbacks();
-  service_callbacks->failure_callback = failure_callback;
-  service_callbacks->create_network_callback = success_callback;
+  service_callbacks->failure_callback = std::move(failure_callback);
+  service_callbacks->create_network_callback = std::move(success_callback);
 
   std::string* network_guid = new std::string;
   std::string* error = new std::string;
@@ -224,10 +224,10 @@
 void NetworkingPrivateServiceClient::ForgetNetwork(
     const std::string& guid,
     bool allow_forget_shared_config,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   // TODO(mef): Implement for Win/Mac
-  failure_callback.Run(networking_private::kErrorNotSupported);
+  std::move(failure_callback).Run(networking_private::kErrorNotSupported);
 }
 
 void NetworkingPrivateServiceClient::GetNetworks(
@@ -235,11 +235,12 @@
     bool configured_only,
     bool visible_only,
     int limit,
-    const NetworkListCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    NetworkListCallback success_callback,
+    FailureCallback failure_callback) {
   ServiceCallbacks* service_callbacks = AddServiceCallbacks();
-  service_callbacks->failure_callback = failure_callback;
-  service_callbacks->get_visible_networks_callback = success_callback;
+  service_callbacks->failure_callback = std::move(failure_callback);
+  service_callbacks->get_visible_networks_callback =
+      std::move(success_callback);
 
   std::unique_ptr<base::ListValue> networks(new base::ListValue);
 
@@ -258,11 +259,11 @@
 
 void NetworkingPrivateServiceClient::StartConnect(
     const std::string& guid,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   ServiceCallbacks* service_callbacks = AddServiceCallbacks();
-  service_callbacks->failure_callback = failure_callback;
-  service_callbacks->start_connect_callback = success_callback;
+  service_callbacks->failure_callback = std::move(failure_callback);
+  service_callbacks->start_connect_callback = std::move(success_callback);
 
   std::string* error = new std::string;
 
@@ -277,11 +278,11 @@
 
 void NetworkingPrivateServiceClient::StartDisconnect(
     const std::string& guid,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
   ServiceCallbacks* service_callbacks = AddServiceCallbacks();
-  service_callbacks->failure_callback = failure_callback;
-  service_callbacks->start_disconnect_callback = success_callback;
+  service_callbacks->failure_callback = std::move(failure_callback);
+  service_callbacks->start_disconnect_callback = std::move(success_callback);
 
   std::string* error = new std::string;
 
@@ -296,18 +297,18 @@
 
 void NetworkingPrivateServiceClient::GetCaptivePortalStatus(
     const std::string& guid,
-    const StringCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  failure_callback.Run(networking_private::kErrorNotSupported);
+    StringCallback success_callback,
+    FailureCallback failure_callback) {
+  std::move(failure_callback).Run(networking_private::kErrorNotSupported);
 }
 
 void NetworkingPrivateServiceClient::UnlockCellularSim(
     const std::string& guid,
     const std::string& pin,
     const std::string& puk,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  failure_callback.Run(networking_private::kErrorNotSupported);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  std::move(failure_callback).Run(networking_private::kErrorNotSupported);
 }
 
 void NetworkingPrivateServiceClient::SetCellularSimState(
@@ -315,17 +316,17 @@
     bool require_pin,
     const std::string& current_pin,
     const std::string& new_pin,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  failure_callback.Run(networking_private::kErrorNotSupported);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  std::move(failure_callback).Run(networking_private::kErrorNotSupported);
 }
 
 void NetworkingPrivateServiceClient::SelectCellularMobileNetwork(
     const std::string& guid,
     const std::string& network_id,
-    const VoidCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  failure_callback.Run(networking_private::kErrorNotSupported);
+    VoidCallback success_callback,
+    FailureCallback failure_callback) {
+  std::move(failure_callback).Run(networking_private::kErrorNotSupported);
 }
 
 std::unique_ptr<base::ListValue>
@@ -397,10 +398,11 @@
   DCHECK(service_callbacks);
   if (!error->empty()) {
     DCHECK(!service_callbacks->failure_callback.is_null());
-    service_callbacks->failure_callback.Run(*error);
+    std::move(service_callbacks->failure_callback).Run(*error);
   } else {
     DCHECK(!service_callbacks->get_properties_callback.is_null());
-    service_callbacks->get_properties_callback.Run(std::move(properties));
+    std::move(service_callbacks->get_properties_callback)
+        .Run(std::move(properties));
   }
   RemoveServiceCallbacks(callback_id);
 }
@@ -411,7 +413,8 @@
   ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id);
   DCHECK(service_callbacks);
   DCHECK(!service_callbacks->get_visible_networks_callback.is_null());
-  service_callbacks->get_visible_networks_callback.Run(std::move(networks));
+  std::move(service_callbacks->get_visible_networks_callback)
+      .Run(std::move(networks));
   RemoveServiceCallbacks(callback_id);
 }
 
@@ -422,10 +425,10 @@
   DCHECK(service_callbacks);
   if (!error->empty()) {
     DCHECK(!service_callbacks->failure_callback.is_null());
-    service_callbacks->failure_callback.Run(*error);
+    std::move(service_callbacks->failure_callback).Run(*error);
   } else {
     DCHECK(!service_callbacks->set_properties_callback.is_null());
-    service_callbacks->set_properties_callback.Run();
+    std::move(service_callbacks->set_properties_callback).Run();
   }
   RemoveServiceCallbacks(callback_id);
 }
@@ -438,10 +441,10 @@
   DCHECK(service_callbacks);
   if (!error->empty()) {
     DCHECK(!service_callbacks->failure_callback.is_null());
-    service_callbacks->failure_callback.Run(*error);
+    std::move(service_callbacks->failure_callback).Run(*error);
   } else {
     DCHECK(!service_callbacks->create_network_callback.is_null());
-    service_callbacks->create_network_callback.Run(*network_guid);
+    std::move(service_callbacks->create_network_callback).Run(*network_guid);
   }
   RemoveServiceCallbacks(callback_id);
 }
@@ -453,10 +456,10 @@
   DCHECK(service_callbacks);
   if (!error->empty()) {
     DCHECK(!service_callbacks->failure_callback.is_null());
-    service_callbacks->failure_callback.Run(*error);
+    std::move(service_callbacks->failure_callback).Run(*error);
   } else {
     DCHECK(!service_callbacks->start_connect_callback.is_null());
-    service_callbacks->start_connect_callback.Run();
+    std::move(service_callbacks->start_connect_callback).Run();
   }
   RemoveServiceCallbacks(callback_id);
 }
@@ -468,10 +471,10 @@
   DCHECK(service_callbacks);
   if (!error->empty()) {
     DCHECK(!service_callbacks->failure_callback.is_null());
-    service_callbacks->failure_callback.Run(*error);
+    std::move(service_callbacks->failure_callback).Run(*error);
   } else {
     DCHECK(!service_callbacks->start_disconnect_callback.is_null());
-    service_callbacks->start_disconnect_callback.Run();
+    std::move(service_callbacks->start_disconnect_callback).Run();
   }
   RemoveServiceCallbacks(callback_id);
 }
diff --git a/extensions/browser/api/networking_private/networking_private_service_client.h b/extensions/browser/api/networking_private/networking_private_service_client.h
index 2269553..073d27953 100644
--- a/extensions/browser/api/networking_private/networking_private_service_client.h
+++ b/extensions/browser/api/networking_private/networking_private_service_client.h
@@ -51,52 +51,51 @@
   void GetManagedProperties(const std::string& guid,
                             PropertiesCallback callback) override;
   void GetState(const std::string& guid,
-                const DictionaryCallback& success_callback,
-                const FailureCallback& failure_callback) override;
+                DictionaryCallback success_callback,
+                FailureCallback failure_callback) override;
   void SetProperties(const std::string& guid,
                      std::unique_ptr<base::DictionaryValue> properties_dict,
                      bool allow_set_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void CreateNetwork(bool shared,
                      std::unique_ptr<base::DictionaryValue> properties_dict,
-                     const StringCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     StringCallback success_callback,
+                     FailureCallback failure_callback) override;
   void ForgetNetwork(const std::string& guid,
                      bool allow_forget_shared_config,
-                     const VoidCallback& success_callback,
-                     const FailureCallback& failure_callback) override;
+                     VoidCallback success_callback,
+                     FailureCallback failure_callback) override;
   void GetNetworks(const std::string& network_type,
                    bool configured_only,
                    bool visible_only,
                    int limit,
-                   const NetworkListCallback& success_callback,
-                   const FailureCallback& failure_callback) override;
+                   NetworkListCallback success_callback,
+                   FailureCallback failure_callback) override;
   void StartConnect(const std::string& guid,
-                    const VoidCallback& success_callback,
-                    const FailureCallback& failure_callback) override;
+                    VoidCallback success_callback,
+                    FailureCallback failure_callback) override;
   void StartDisconnect(const std::string& guid,
-                       const VoidCallback& success_callback,
-                       const FailureCallback& failure_callback) override;
+                       VoidCallback success_callback,
+                       FailureCallback failure_callback) override;
   void GetCaptivePortalStatus(const std::string& guid,
-                              const StringCallback& success_callback,
-                              const FailureCallback& failure_callback) override;
+                              StringCallback success_callback,
+                              FailureCallback failure_callback) override;
   void UnlockCellularSim(const std::string& guid,
                          const std::string& pin,
                          const std::string& puk,
-                         const VoidCallback& success_callback,
-                         const FailureCallback& failure_callback) override;
+                         VoidCallback success_callback,
+                         FailureCallback failure_callback) override;
   void SetCellularSimState(const std::string& guid,
                            bool require_pin,
                            const std::string& current_pin,
                            const std::string& new_pin,
-                           const VoidCallback& success_callback,
-                           const FailureCallback& failure_callback) override;
-  void SelectCellularMobileNetwork(
-      const std::string& guid,
-      const std::string& network_id,
-      const VoidCallback& success_callback,
-      const FailureCallback& failure_callback) override;
+                           VoidCallback success_callback,
+                           FailureCallback failure_callback) override;
+  void SelectCellularMobileNetwork(const std::string& guid,
+                                   const std::string& network_id,
+                                   VoidCallback success_callback,
+                                   FailureCallback failure_callback) override;
   std::unique_ptr<base::ListValue> GetEnabledNetworkTypes() override;
   std::unique_ptr<DeviceStateList> GetDeviceStateList() override;
   std::unique_ptr<base::DictionaryValue> GetGlobalPolicy() override;
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc
index edc6cbb..ef4eaf1 100644
--- a/gpu/command_buffer/service/service_utils.cc
+++ b/gpu/command_buffer/service/service_utils.cc
@@ -94,18 +94,7 @@
 }
 
 bool PassthroughCommandDecoderSupported() {
-#if defined(USE_EGL)
-  // Using the passthrough command buffer requires that specific ANGLE
-  // extensions are exposed
-  return gl::GLSurfaceEGL::IsCreateContextBindGeneratesResourceSupported() &&
-         gl::GLSurfaceEGL::IsCreateContextWebGLCompatabilitySupported() &&
-         gl::GLSurfaceEGL::IsRobustResourceInitSupported() &&
-         gl::GLSurfaceEGL::IsDisplayTextureShareGroupSupported() &&
-         gl::GLSurfaceEGL::IsCreateContextClientArraysSupported();
-#else
-  // The passthrough command buffer is only supported on top of ANGLE/EGL
-  return false;
-#endif  // defined(USE_EGL)
+  return gl::PassthroughCommandDecoderSupported();
 }
 
 GpuPreferences ParseGpuPreferences(const base::CommandLine* command_line) {
diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
index 992a7d9..8f9eb62b 100644
--- a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
+++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
@@ -77,26 +77,17 @@
                                public gpu::GpuCommandBufferTestEGL {
  public:
   GpuMemoryBufferTestEGL()
-      : egl_gles2_initialized_(false),
-        native_pixmap_factory_(gfx::CreateClientNativePixmapFactoryDmabuf()) {}
+      : native_pixmap_factory_(gfx::CreateClientNativePixmapFactoryDmabuf()) {}
 
  protected:
   void SetUp() override {
-    // TODO(jonahr): Test setup fails on Linux with ANGLE/passthrough
-    // (crbug.com/1099766)
-    gpu::GPUTestBotConfig bot_config;
-    if (bot_config.LoadCurrentConfig(nullptr) &&
-        bot_config.Matches("linux passthrough")) {
-      return;
-    }
-
-    egl_gles2_initialized_ = InitializeEGLGLES2(kImageWidth, kImageHeight);
+    egl_initialized_ = InitializeEGL(kImageWidth, kImageHeight);
     gl_.set_use_native_pixmap_memory_buffers(true);
   }
 
   void TearDown() override { RestoreGLDefault(); }
 
-  bool egl_gles2_initialized_;
+  bool egl_initialized_{false};
   std::unique_ptr<gfx::ClientNativePixmapFactory> native_pixmap_factory_;
 };
 #endif  // defined(OS_LINUX)
@@ -377,7 +368,7 @@
 // It can be the case when vaapi is setup in a media service hosted in a
 // dedicated process, i.e. not the gpu process.
 TEST_F(GpuMemoryBufferTestEGL, GLCreateImageCHROMIUMFromNativePixmap) {
-  SKIP_TEST_IF(!egl_gles2_initialized_);
+  SKIP_TEST_IF(!egl_initialized_);
 
   // This extension is required for glCreateImageCHROMIUM on Linux.
   SKIP_TEST_IF(!HasEGLExtension("EGL_EXT_image_dma_buf_import"));
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 3758210..6d051bf 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -61,9 +61,6 @@
     const base::CommandLine& command_line,
     GpuPreferences* preferences) {
   // Only initialize specific GpuPreferences members used for testing.
-  // GPUTestBotConfig::LoadCurrentConfig uses the same method to determine
-  // which command decoder should match the test config. Any updates to this
-  // function should be forwarded to gpu_test_config.cc
   preferences->use_passthrough_cmd_decoder =
       gles2::UsePassthroughCommandDecoder(&command_line);
 }
diff --git a/gpu/command_buffer/tests/gl_oes_egl_image_unittest.cc b/gpu/command_buffer/tests/gl_oes_egl_image_unittest.cc
index 828ea309..207d0c2 100644
--- a/gpu/command_buffer/tests/gl_oes_egl_image_unittest.cc
+++ b/gpu/command_buffer/tests/gl_oes_egl_image_unittest.cc
@@ -35,20 +35,12 @@
                            public gpu::GpuCommandBufferTestEGL {
  protected:
   void SetUp() override {
-    // TODO(jonahr): Test setup fails on Linux with ANGLE/passthrough
-    // (crbug.com/1099766)
-    gpu::GPUTestBotConfig bot_config;
-    if (bot_config.LoadCurrentConfig(nullptr) &&
-        bot_config.Matches("linux passthrough")) {
-      return;
-    }
-
-    egl_gles2_initialized_ = InitializeEGLGLES2(kImageWidth, kImageHeight);
+    egl_initialized_ = InitializeEGL(kImageWidth, kImageHeight);
   }
 
   void TearDown() override { RestoreGLDefault(); }
 
-  bool egl_gles2_initialized_;
+  bool egl_initialized_{false};
 };
 
 #if defined(OS_LINUX)
@@ -86,7 +78,7 @@
 // texture and verifies that the colors match with the pixels uploaded into
 // the initial GL texture.
 TEST_F(GpuOESEGLImageTest, EGLImageToTexture) {
-  SKIP_TEST_IF(!egl_gles2_initialized_);
+  SKIP_TEST_IF(!egl_initialized_);
 
   // This extension is required for creating an EGLImage from a GL texture.
   SKIP_TEST_IF(!HasEGLExtension("EGL_KHR_image_base"));
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc
index 67e3041..5c81993 100644
--- a/gpu/command_buffer/tests/gl_test_utils.cc
+++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -380,36 +380,41 @@
 
 GpuCommandBufferTestEGL::~GpuCommandBufferTestEGL() {}
 
-bool GpuCommandBufferTestEGL::InitializeEGLGLES2(int width, int height) {
-  if (gl::GetGLImplementation() !=
-      gl::GLImplementation::kGLImplementationEGLGLES2) {
-    const auto impls = gl::init::GetAllowedGLImplementations();
-    if (!base::Contains(impls,
-                        gl::GLImplementation::kGLImplementationEGLGLES2)) {
-      LOG(INFO) << "Skip test, implementation EGLGLES2 is not available";
-      return false;
-    }
-
+bool GpuCommandBufferTestEGL::InitializeEGL(int width, int height) {
+  gl::GLImplementation current_impl = gl::GetGLImplementation();
+  if (!(current_impl == gl::kGLImplementationEGLGLES2 ||
+        current_impl == gl::kGLImplementationEGLANGLE)) {
     gpu::GPUInfo gpu_info;
     gpu::CollectContextGraphicsInfo(&gpu_info);
+    gpu::CollectBasicGraphicsInfo(base::CommandLine::ForCurrentProcess(),
+                                  &gpu_info);
     // See crbug.com/822716, the ATI proprietary driver has eglGetProcAddress
     // but eglInitialize crashes with x11.
     if (gpu_info.gl_vendor.find("ATI Technologies Inc.") != std::string::npos) {
       LOG(INFO) << "Skip test, ATI proprietary driver crashes with egl/x11";
       return false;
     }
+    // The native EGL driver is not supported with the passthrough command
+    // decoder, in that case use ANGLE
+    const gl::GLImplementation new_impl =
+        (gpu_info.passthrough_cmd_decoder ? gl::kGLImplementationEGLANGLE
+                                          : gl::kGLImplementationEGLGLES2);
+    const auto allowed_impls = gl::init::GetAllowedGLImplementations();
+    if (!base::Contains(allowed_impls, new_impl)) {
+      LOG(INFO) << "Skip test, no EGL implementation is available";
+      return false;
+    }
 
     gl_reinitialized_ = true;
     gl::init::ShutdownGL(false /* due_to_fallback */);
-    if (!GLTestHelper::InitializeGL(
-            gl::GLImplementation::kGLImplementationEGLGLES2)) {
-      LOG(INFO) << "Skip test, failed to initialize EGLGLES2";
+    if (!GLTestHelper::InitializeGL(new_impl)) {
+      LOG(INFO) << "Skip test, failed to initialize EGL";
       return false;
     }
   }
-
-  DCHECK_EQ(gl::GLImplementation::kGLImplementationEGLGLES2,
-            gl::GetGLImplementation());
+  current_impl = gl::GetGLImplementation();
+  DCHECK(current_impl == gl::kGLImplementationEGLGLES2 ||
+         current_impl == gl::kGLImplementationEGLANGLE);
 
   // Make the GL context current now to get all extensions.
   GLManager::Options options;
diff --git a/gpu/command_buffer/tests/gl_test_utils.h b/gpu/command_buffer/tests/gl_test_utils.h
index 1e36968..8dfb638 100644
--- a/gpu/command_buffer/tests/gl_test_utils.h
+++ b/gpu/command_buffer/tests/gl_test_utils.h
@@ -102,10 +102,10 @@
   GpuCommandBufferTestEGL();
   ~GpuCommandBufferTestEGL();
 
-  // Reinitialize GL to the EGLGLES2 implementation if it is available and not
-  // the current initialized GL implementation. Return true on sucess, false
+  // Reinitialize GL to an EGL implementation if it is available and not
+  // the current initialized GL implementation. Return true on success, false
   // otherwise.
-  bool InitializeEGLGLES2(int width, int height);
+  bool InitializeEGL(int width, int height);
 
   // Restore the default GL implementation.
   void RestoreGLDefault();
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index a798e0a1..4f12ac4 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -30,6 +30,7 @@
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/gl_switches.h"
+#include "ui/gl/gl_utils.h"
 #include "ui/gl/gl_version_info.h"
 #include "ui/gl/init/create_gr_gl_interface.h"
 #include "ui/gl/init/gl_factory.h"
@@ -213,6 +214,9 @@
   std::string use_gl = command_line->GetSwitchValueASCII(switches::kUseGL);
   std::string use_angle =
       command_line->GetSwitchValueASCII(switches::kUseANGLE);
+  gpu_info->passthrough_cmd_decoder =
+      gl::UsePassthroughCommandDecoder(command_line) &&
+      gl::PassthroughCommandDecoderSupported();
 
   // If GL is disabled then we don't need GPUInfo.
   if (use_gl == gl::kGLImplementationDisabledName) {
diff --git a/gpu/config/gpu_test_config.cc b/gpu/config/gpu_test_config.cc
index 4c60d73..735e132b 100644
--- a/gpu/config/gpu_test_config.cc
+++ b/gpu/config/gpu_test_config.cc
@@ -196,6 +196,11 @@
   ClearGPUVendor();
   AddGPUVendor(gpu_info.gpu.vendor_id);
   set_gpu_device_id(gpu_info.gpu.device_id);
+  if (gpu_info.passthrough_cmd_decoder) {
+    set_command_decoder(kCommandDecoderPassthrough);
+  } else {
+    set_command_decoder(kCommandDecoderValidating);
+  }
   return true;
 }
 
@@ -286,7 +291,8 @@
     rt = false;
 #else
     GPUInfo my_gpu_info;
-    if (!CollectBasicGraphicsInfo(&my_gpu_info)) {
+    if (!CollectBasicGraphicsInfo(base::CommandLine::ForCurrentProcess(),
+                                  &my_gpu_info)) {
       LOG(ERROR) << "Fail to identify GPU";
       rt = false;
     } else {
@@ -306,14 +312,6 @@
 #else
   set_build_type(kBuildTypeDebug);
 #endif
-  // GLManager::Initialize uses this function to determine which command decoder
-  // to be run under these tests. The test config should do the same.
-  if (gl::UsePassthroughCommandDecoder(
-          base::CommandLine::ForCurrentProcess())) {
-    set_command_decoder(kCommandDecoderPassthrough);
-  } else {
-    set_command_decoder(kCommandDecoderValidating);
-  }
   return rt;
 }
 
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index 64826cc3..8f9e65b 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -374,11 +374,12 @@
   bool gl_disabled = gl::GetGLImplementation() == gl::kGLImplementationDisabled;
 
   // Compute passthrough decoder status before ComputeGpuFeatureInfo below.
+  // Do this after GL is initialized so extensions can be queried.
   gpu_info_.passthrough_cmd_decoder =
       gles2::UsePassthroughCommandDecoder(command_line) &&
       gles2::PassthroughCommandDecoderSupported();
 
-  // We need to collect GL strings (VENDOR, RENDERER) for blocklisting purposes.
+  // We need to collect GL strings (VENDOR, RENDERER) for blacklisting purposes.
   if (!gl_disabled) {
     if (!gl_use_swiftshader_) {
       if (!CollectGraphicsInfo(&gpu_info_))
@@ -718,6 +719,8 @@
   gpu_feature_info_for_hardware_gpu_ = gpu_feature_info_;
   gpu_feature_info_ = ComputeGpuFeatureInfoForSwiftShader();
   CollectContextGraphicsInfo(&gpu_info_);
+
+  DCHECK_EQ(gpu_info_.passthrough_cmd_decoder, false);
 }
 
 scoped_refptr<gl::GLSurface> GpuInit::TakeDefaultOffscreenSurface() {
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 94e2b2a..3ea0166 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -9152,7 +9152,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"packages\":[{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/25.0.2.yaml\",\"sdk_package_name\":\"build-tools;25.0.2\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/27.0.3.yaml\",\"sdk_package_name\":\"build-tools;27.0.3\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/29.0.2.yaml\",\"sdk_package_name\":\"build-tools;29.0.2\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/cmdline-tools.yaml\",\"sdk_package_name\":\"cmdline-tools;latest\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/emulator.yaml\",\"sdk_package_name\":\"emulator\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/extras/google/gcm.yaml\",\"sdk_package_name\":\"extras;google;gcm\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/patcher/v4.yaml\",\"sdk_package_name\":\"patcher;v4\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-23.yaml\",\"sdk_package_name\":\"platforms;android-23\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-28.yaml\",\"sdk_package_name\":\"platforms;android-28\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-29.yaml\",\"sdk_package_name\":\"platforms;android-29\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-30.yaml\",\"sdk_package_name\":\"platforms;android-30\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platform-tools.yaml\",\"sdk_package_name\":\"platform-tools\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/sources/android-28.yaml\",\"sdk_package_name\":\"sources;android-28\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/sources/android-29.yaml\",\"sdk_package_name\":\"sources;android-29\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/sources/android-30.yaml\",\"sdk_package_name\":\"sources;android-30\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-23/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-23;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-28/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-28;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-29/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-29;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-29/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-29;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-30/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-30;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-30/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-30;google_apis_playstore;x86\"}],\"recipe\":\"android/sdk_packager\"}"
+      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"packages\":[{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/25.0.2.yaml\",\"sdk_package_name\":\"build-tools;25.0.2\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/27.0.3.yaml\",\"sdk_package_name\":\"build-tools;27.0.3\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/29.0.2.yaml\",\"sdk_package_name\":\"build-tools;29.0.2\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/30.0.1.yaml\",\"sdk_package_name\":\"build-tools;30.0.1\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/cmdline-tools.yaml\",\"sdk_package_name\":\"cmdline-tools;latest\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/emulator.yaml\",\"sdk_package_name\":\"emulator\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/extras/google/gcm.yaml\",\"sdk_package_name\":\"extras;google;gcm\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/patcher/v4.yaml\",\"sdk_package_name\":\"patcher;v4\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-23.yaml\",\"sdk_package_name\":\"platforms;android-23\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-28.yaml\",\"sdk_package_name\":\"platforms;android-28\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-29.yaml\",\"sdk_package_name\":\"platforms;android-29\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-30.yaml\",\"sdk_package_name\":\"platforms;android-30\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platform-tools.yaml\",\"sdk_package_name\":\"platform-tools\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/sources/android-28.yaml\",\"sdk_package_name\":\"sources;android-28\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/sources/android-29.yaml\",\"sdk_package_name\":\"sources;android-29\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-23/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-23;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-28/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-28;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-29/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-29;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-29/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-29;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-30/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-30;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-30/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-30;google_apis_playstore;x86\"}],\"recipe\":\"android/sdk_packager\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/subprojects/chromium/master-only/ci.star b/infra/config/subprojects/chromium/master-only/ci.star
index b4ddce4b..361ebdfd 100644
--- a/infra/config/subprojects/chromium/master-only/ci.star
+++ b/infra/config/subprojects/chromium/master-only/ci.star
@@ -93,6 +93,10 @@
                 'cipd_yaml': 'third_party/android_sdk/cipd/build-tools/29.0.2.yaml'
             },
             {
+                'sdk_package_name': 'build-tools;30.0.1',
+                'cipd_yaml': 'third_party/android_sdk/cipd/build-tools/30.0.1.yaml'
+            },
+            {
                 'sdk_package_name': 'cmdline-tools;latest',
                 'cipd_yaml': 'third_party/android_sdk/cipd/cmdline-tools.yaml'
             },
@@ -136,10 +140,11 @@
                 'sdk_package_name': 'sources;android-29',
                 'cipd_yaml': 'third_party/android_sdk/cipd/sources/android-29.yaml'
             },
-            {
-                'sdk_package_name': 'sources;android-30',
-                'cipd_yaml': 'third_party/android_sdk/cipd/sources/android-30.yaml'
-            },
+            # Not yet available as R is not released to AOSP.
+            #{
+            #    'sdk_package_name': 'sources;android-30',
+            #    'cipd_yaml': 'third_party/android_sdk/cipd/sources/android-30.yaml'
+            #},
             {
                 'sdk_package_name': 'system-images;android-23;google_apis;x86',
                 'cipd_yaml': 'third_party/android_sdk/cipd/system_images/android-23/google_apis/x86.yaml'
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm
index 2729881f..bdc925b 100644
--- a/ios/chrome/app/application_delegate/app_state.mm
+++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -462,6 +462,11 @@
         NO;
   }
 
+  // Trigger UI teardown on iOS 12.
+  if (!IsSceneStartupSupported()) {
+    self.mainSceneState.activationLevel = SceneActivationLevelUnattached;
+  }
+
   [_startupInformation stopChromeMain];
 }
 
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index f638a2d..d49aa0c 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -699,12 +699,6 @@
 }
 
 - (void)stopChromeMain {
-  // Teardown UI state that is associated with scenes.
-  for (SceneState* sceneState in self.appState.connectedScenes) {
-    sceneState.activationLevel = SceneActivationLevelUnattached;
-  }
-  // End of per-window code.
-
   OmahaService::Stop();
 
   [_spotlightManager shutdown];
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm
index 40f34c6..d63e086 100644
--- a/ios/chrome/browser/passwords/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -15,6 +15,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
@@ -22,6 +23,7 @@
 #include "components/autofill/ios/form_util/form_activity_params.h"
 #include "components/password_manager/core/browser/mock_password_store.h"
 #include "components/password_manager/core/browser/password_form_manager.h"
+#include "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_onboarding.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
@@ -68,6 +70,8 @@
 using autofill::PasswordForm;
 using autofill::PasswordFormFillData;
 using base::SysUTF8ToNSString;
+using FillingAssistance =
+    password_manager::PasswordFormMetricsRecorder::FillingAssistance;
 using password_manager::PasswordFormManagerForUI;
 using password_manager::PasswordFormManager;
 using password_manager::PasswordStoreConsumer;
@@ -163,6 +167,7 @@
   form.signon_realm = origin_url;
   form.username_value = ASCIIToUTF16(username_value);
   form.password_value = ASCIIToUTF16(password_value);
+  form.in_store = autofill::PasswordForm::Store::kProfileStore;
   return form;
 }
 
@@ -203,6 +208,13 @@
 
 @end
 
+@interface JsPasswordManager (Testing)
+
+// Provides access to JavaScript Manager for testing with mocks.
+@property BOOL noFormsSeen;
+
+@end
+
 // Real FormSuggestionController is wrapped to register the addition of
 // suggestions.
 @interface PasswordsTestSuggestionController : FormSuggestionController
@@ -225,14 +237,10 @@
 // that the fail is handled correctly.
 @interface FakeJsPasswordManager : JsPasswordManager
 
-- (void)fillPasswordForm:(std::unique_ptr<base::Value>)form
-                 inFrame:(web::WebFrame*)frame
-            withUsername:(NSString*)username
-                password:(NSString*)password
-       completionHandler:(void (^)(NSString*))completionHandler;
+- (void)findPasswordFormsInFrame:(web::WebFrame*)frame
+               completionHandler:(void (^)(NSString*))completionHandler;
 
-// Can be set to YES to mock filing failure on the next call.
-@property BOOL will_fail;
+@property BOOL noFormsSeen;
 
 - (instancetype)init;
 
@@ -243,26 +251,20 @@
 - (instancetype)init {
   self = [super init];
   if (self) {
-    _will_fail = YES;
+    _noFormsSeen = YES;
   }
   return self;
 }
 
-- (void)fillPasswordForm:(std::unique_ptr<base::Value>)form
-                 inFrame:(web::WebFrame*)frame
-            withUsername:(NSString*)username
-                password:(NSString*)password
-       completionHandler:(void (^)(NSString*))completionHandler {
-  if (_will_fail) {
-    _will_fail = NO;
-    completionHandler(@"false");
-  } else {
-    [super fillPasswordForm:std::move(form)
-                    inFrame:frame
-               withUsername:username
-                   password:password
-          completionHandler:(void (^)(NSString*))completionHandler];
-  }
+- (void)findPasswordFormsInFrame:(web::WebFrame*)frame
+               completionHandler:(void (^)(NSString*))completionHandler {
+  DCHECK(completionHandler);
+  auto fakeCompletionHandler = ^(NSString* res) {
+    _noFormsSeen = [res isEqualToString:@"[]"] ? YES : NO;
+    completionHandler(res);
+  };
+  [super findPasswordFormsInFrame:frame
+                completionHandler:fakeCompletionHandler];
 }
 
 @end
@@ -2096,3 +2098,87 @@
     return frames.size() == 1;
   }));
 }
+
+TEST_F(PasswordControllerTest, PasswordMetricsNoSavedCredentials) {
+  base::HistogramTester histogram_tester;
+  {
+    ON_CALL(*store_, GetLogins)
+        .WillByDefault(WithArg<1>(InvokeEmptyConsumerWithForms()));
+    LoadHtml(@"<html><body>"
+              "<form name='login_form' id='login_form'>"
+              "  <input type='text' name='username'>"
+              "  <input type='password' name='password'>"
+              "  <button id='submit_button' value='Submit'>"
+              "</form>"
+              "</body></html>");
+    WaitForFormManagersCreation();
+
+    std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+    EXPECT_CALL(*weak_client_, PromptUserToSaveOrUpdatePasswordPtr)
+        .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+
+    std::string main_frame_id = web::GetMainWebFrameId(web_state());
+    ExecuteJavaScript(
+        @"document.getElementsByName('username')[0].value = 'user';"
+         "document.getElementsByName('password')[0].value = 'pw';"
+         "document.getElementById('submit_button').click();");
+    LoadHtmlWithRendererInitiatedNavigation(
+        @"<html><body>Success</body></html>");
+
+    auto& form_manager_check = form_manager_to_save;
+    ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool() {
+      return form_manager_check != nullptr;
+    }));
+  }
+
+  histogram_tester.ExpectUniqueSample("PasswordManager.FillingAssistance",
+                                      FillingAssistance::kNoSavedCredentials,
+                                      1);
+}
+
+TEST_F(PasswordControllerTest, PasswordMetricsAutomatic) {
+  base::HistogramTester histogram_tester;
+
+  passwordController_.formHelper.jsPasswordManager =
+      [[FakeJsPasswordManager alloc] init];
+
+  PasswordForm form(CreatePasswordForm(BaseUrl().c_str(), "user", "pw"));
+  EXPECT_CALL(*store_, GetLogins)
+      .WillRepeatedly(WithArg<1>(InvokeConsumer(form)));
+
+  LoadHtml(@"<html><body>"
+            "<form name='login_form' id='login_form'>"
+            "  <input type='text' name='username'>"
+            "  <input type='password' name='password'>"
+            "  <button id='submit_button' value='Submit'>"
+            "</form>"
+            "</body></html>");
+  WaitForFormManagersCreation();
+
+  PasswordFormFillData form_data;
+  SetPasswordFormFillData(BaseUrl(), "login_form", 0, "username", 1, "user",
+                          "password", 2, "pw", nullptr, nullptr, false,
+                          &form_data);
+  __block BOOL block_was_called = NO;
+  __block BOOL return_value = NO;
+  [passwordController_ fillPasswordForm:form_data
+                      completionHandler:^(BOOL success) {
+                        block_was_called = YES;
+                        return_value = success;
+                      }];
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool() {
+    return block_was_called;
+  }));
+
+  ExecuteJavaScript(
+      @"var e = new UIEvent('touchend');"
+       "document.getElementById('submit_button').dispatchEvent(e);");
+  LoadHtmlWithRendererInitiatedNavigation(@"<html><body>Success</body></html>");
+
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool() {
+    return passwordController_.formHelper.jsPasswordManager.noFormsSeen;
+  }));
+
+  histogram_tester.ExpectUniqueSample("PasswordManager.FillingAssistance",
+                                      FillingAssistance::kAutomatic, 1);
+}
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
index c7a5eea..68e2bf7 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
@@ -31,6 +31,7 @@
 #endif  // defined(CHROME_EARL_GREY_2)
 
 using base::TimeDelta;
+using base::test::ios::kWaitForUIElementTimeout;
 using base::test::ios::SpinRunLoopWithMinDelay;
 using base::test::ios::WaitUntilConditionOrTimeout;
 using chrome_test_util::TapWebElementWithId;
@@ -105,7 +106,7 @@
 
   // Brings up the keyboard by tapping on one of the form's field.
   TapOnWebElementWithID(kFormElementID1);
-  SpinRunLoopWithMinDelay(TimeDelta::FromSeconds(1));
+  SpinRunLoopWithMinDelay(TimeDelta::FromSeconds(kWaitForUIElementTimeout));
 
   // Verifies that the taped element is focused.
   AssertElementIsFocused(kFormElementID1);
@@ -117,7 +118,7 @@
 
   // Tap the "Submit" button, and let the run loop spin.
   TapOnWebElementWithID(kFormElementSubmit);
-  SpinRunLoopWithMinDelay(TimeDelta::FromSeconds(1));
+  SpinRunLoopWithMinDelay(TimeDelta::FromSeconds(kWaitForUIElementTimeout));
 
   // Verify the state changed.
   GREYAssertFalse(observer.keyboardState.isVisible,
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index 9c5af81..a5d5c0f5 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -368,8 +368,12 @@
                .userActivities) {
         if (ActivityIsURLLoad(activity)) {
           UrlLoadParams params = LoadParamsFromActivity(activity);
-          UrlLoadingBrowserAgent::FromBrowser(self.mainInterface.browser)
-              ->Load(params);
+          ApplicationMode mode = params.in_incognito
+                                     ? ApplicationMode::INCOGNITO
+                                     : ApplicationMode::NORMAL;
+          [self openOrReuseTabInMode:mode
+                   withUrlLoadParams:params
+                 tabOpenedCompletion:nil];
         } else if (!activityWithCompletion) {
           // Completion involves user interaction.
           // Only one can be triggered.
@@ -1453,8 +1457,24 @@
 
     return YES;
   }
+  BOOL hasPendingURL = NO;
+
+  if (@available(iOS 13, *)) {
+    // Only consider normal mode load as this function always returns NO for
+    // incognito browser.
+    for (NSUserActivity* activity in self.sceneState.connectionOptions
+             .userActivities) {
+      if (ActivityIsURLLoadInNormalMode(activity)) {
+        hasPendingURL = YES;
+        break;
+      }
+    }
+  }
+
+  // If there is a URLLoading activity, avoid opening a new tab as the NTP would
+  // flash before the target URL is loaded.
   return browser->GetWebStateList()->empty() &&
-         !(browser->GetBrowserState()->IsOffTheRecord());
+         !(browser->GetBrowserState()->IsOffTheRecord()) && !hasPendingURL;
 }
 
 #pragma mark - SceneURLLoadingServiceDelegate
@@ -1686,7 +1706,6 @@
   }
 }
 
-
 // Checks the target BVC's current tab's URL. If this URL is chrome://newtab,
 // loads |urlLoadParams| in this tab. Otherwise, open |urlLoadParams| in a new
 // tab in the target BVC. |tabDisplayedCompletion| will be called on the new tab
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
index 0dfc9b34..5790133b 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
@@ -125,7 +125,7 @@
       break;
 #endif  // !defined(NDEBUG)
     case PopupMenuActionOpenNewWindow:
-      [self.dispatcher openNewWindowWithActivity:ActivityToOpenNewTab(false)];
+      [self.dispatcher openNewWindowWithActivity:nil];
       break;
     case PopupMenuActionBookmarks:
       RecordAction(UserMetricsAction("MobileMenuAllBookmarks"));
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_edit_credit_card_egtest.mm b/ios/chrome/browser/ui/settings/autofill/autofill_edit_credit_card_egtest.mm
index 2253aee..876e6ca 100644
--- a/ios/chrome/browser/ui/settings/autofill/autofill_edit_credit_card_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill/autofill_edit_credit_card_egtest.mm
@@ -108,7 +108,8 @@
 }
 
 // Tests that clearing a nickname is allowed.
-- (void)testEmptyNickname {
+// Disabled due to: crbug.com/1106766
+- (void)DISABLED_testEmptyNickname {
   [[EarlGrey selectElementWithMatcher:NicknameTextField()]
       performAction:grey_typeText(@"To be removed")];
 
diff --git a/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn b/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn
index 4719b99..1e004bfd 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn
@@ -48,12 +48,46 @@
     "//components/autofill/core/common",
     "//components/password_manager/core/browser:browser",
     "//components/strings",
+    "//ios/chrome/app/strings:ios_strings_grit",
     "//ios/chrome/browser",
     "//ios/chrome/browser/ui/settings:settings_root",
     "//ios/chrome/browser/ui/settings/autofill",
     "//ios/chrome/browser/ui/table_view/cells",
+    "//ios/chrome/browser/ui/table_view/cells:cells_constants",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/util",
     "//ui/base",
   ]
 }
+
+source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [ "password_detials_view_controller_unittest.mm" ]
+  deps = [
+    ":password_details",
+    ":password_details_ui",
+    "//base",
+    "//base/test:test_support",
+    "//components/autofill/core/common",
+    "//components/password_manager/core/browser:test_support",
+    "//components/password_manager/core/common",
+    "//components/strings",
+    "//ios/chrome/app/strings",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/passwords",
+    "//ios/chrome/browser/ui/settings/cells",
+    "//ios/chrome/browser/ui/table_view:test_support",
+    "//ios/chrome/browser/ui/table_view/cells",
+    "//ios/chrome/browser/ui/table_view/cells:cells_constants",
+    "//ios/chrome/browser/ui/util",
+    "//ios/chrome/common/ui/colors",
+    "//ios/chrome/test/app:test_support",
+    "//ios/web/public/test",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base",
+    "//url",
+  ]
+}
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm
index 464d031..8a67b7c 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm
@@ -7,12 +7,33 @@
 #include "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+namespace {
+
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  SectionIdentifierPassword = kSectionIdentifierEnumZero,
+  // TODO:(crbug.com/1075494) - Add password compromised section.
+};
+
+typedef NS_ENUM(NSInteger, ItemType) {
+  ItemTypeWebsite = kItemTypeEnumZero,
+  ItemTypeUsername,
+  ItemTypePassword,
+};
+
+}  // namespace
+
 @interface PasswordDetailsViewController ()
 
 // Password which is shown on the screen.
@@ -32,10 +53,133 @@
   [self loadModel];
 }
 
+- (void)viewDidDisappear:(BOOL)animated {
+  [self.handler passwordDetailsViewControllerDidDisappear];
+  [super viewDidDisappear:animated];
+}
+
 #pragma mark - ChromeTableViewController
 
+- (void)editButtonPressed {
+  [super editButtonPressed];
+
+  if (!self.tableView.editing) {
+    // TODO:(crbug.com/1075494) - Update |_password| accordingly.
+    [self.delegate passwordDetailsViewController:self
+                          didEditPasswordDetails:self.password];
+  }
+
+  [self loadModel];
+  [self reconfigureCellsForItems:
+            [self.tableViewModel
+                itemsInSectionWithIdentifier:SectionIdentifierPassword]];
+}
+
 - (void)loadModel {
   [super loadModel];
+  self.title = self.password.origin;
+
+  TableViewModel* model = self.tableViewModel;
+  [model addSectionWithIdentifier:SectionIdentifierPassword];
+
+  [model addItem:[self websiteItem]
+      toSectionWithIdentifier:SectionIdentifierPassword];
+
+  [model addItem:[self usernameItem]
+      toSectionWithIdentifier:SectionIdentifierPassword];
+
+  [model addItem:[self passwordItem]
+      toSectionWithIdentifier:SectionIdentifierPassword];
+}
+
+#pragma mark - Items
+
+- (TableViewTextEditItem*)websiteItem {
+  TableViewTextEditItem* item =
+      [[TableViewTextEditItem alloc] initWithType:ItemTypeWebsite];
+  item.textFieldName = l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_SITE);
+  item.textFieldValue = self.password.website;
+  item.textFieldEnabled = NO;
+  item.hideIcon = YES;
+  return item;
+}
+
+- (TableViewTextEditItem*)usernameItem {
+  TableViewTextEditItem* item =
+      [[TableViewTextEditItem alloc] initWithType:ItemTypeUsername];
+  item.textFieldName =
+      l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME);
+  item.textFieldValue = self.password.username;
+  item.textFieldEnabled = NO;
+  item.hideIcon = YES;
+  return item;
+}
+
+- (TableViewTextEditItem*)passwordItem {
+  TableViewTextEditItem* item =
+      [[TableViewTextEditItem alloc] initWithType:ItemTypePassword];
+  item.textFieldName =
+      l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
+  item.textFieldValue = kMaskedPassword;
+  item.textFieldEnabled = self.tableView.editing;
+  item.hideIcon = !self.tableView.editing;
+  item.autoCapitalizationType = UITextAutocapitalizationTypeNone;
+  item.keyboardType = UIKeyboardTypeURL;
+  item.returnKeyType = UIReturnKeyDone;
+  // TODO:(crbug.com/1075494) - Add eye icon to view password.
+  return item;
+}
+
+#pragma mark - UITableViewDelegate
+
+- (void)tableView:(UITableView*)tableView
+    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
+  if (self.tableView.editing) {
+    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
+    TableViewTextEditCell* textFieldCell =
+        base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
+    [textFieldCell.textField becomeFirstResponder];
+  }
+}
+
+- (UITableViewCellEditingStyle)tableView:(UITableView*)tableView
+           editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath {
+  return UITableViewCellEditingStyleNone;
+}
+
+- (BOOL)tableView:(UITableView*)tableview
+    shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath*)indexPath {
+  return NO;
+}
+
+#pragma mark - UITableViewDataSource
+
+- (UITableViewCell*)tableView:(UITableView*)tableView
+        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
+  UITableViewCell* cell = [super tableView:tableView
+                     cellForRowAtIndexPath:indexPath];
+
+  cell.selectionStyle = UITableViewCellSelectionStyleNone;
+
+  // TODO:(crbug.com/1075494) - Add action to Show/Hide password when user tap
+  // eye icon.
+  TableViewTextEditCell* textFieldCell =
+      base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
+  textFieldCell.textField.delegate = self;
+  return textFieldCell;
+}
+
+- (BOOL)tableView:(UITableView*)tableView
+    canEditRowAtIndexPath:(NSIndexPath*)indexPath {
+  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
+  switch (itemType) {
+    case ItemTypeWebsite:
+    case ItemTypeUsername:
+      return NO;
+    case ItemTypePassword:
+      return YES;
+  }
+  return NO;
 }
 
 #pragma mark - PasswordDetailsConsumer
@@ -45,4 +189,16 @@
   [self reloadData];
 }
 
+#pragma mark - Private
+
+// Called when user tapped Delete button during editing. It means presented
+// password should be deleted.
+- (void)deleteItems:(NSArray<NSIndexPath*>*)indexPaths {
+  // TODO:(crbug.com/1075494) - Show Confirmation dialog and delete password.
+}
+
+- (BOOL)shouldHideToolbar {
+  return !self.editing;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_detials_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_details/password_detials_view_controller_unittest.mm
new file mode 100644
index 0000000..cbd044d
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_detials_view_controller_unittest.mm
@@ -0,0 +1,127 @@
+// 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 "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/password_form.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h"
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h"
+#include "ios/chrome/grit/ios_chromium_strings.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ios/web/public/test/web_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// Test class that conforms to PasswordDetailsHanler in order to test the
+// presenter methods are called correctly.
+@interface FakePasswordDetailsHandler : NSObject <PasswordDetailsHandler>
+@end
+
+@implementation FakePasswordDetailsHandler
+
+// Called when the view controller was dismissed.
+- (void)passwordDetailsViewControllerDidDisappear {
+}
+
+@end
+
+// Test class that conforms to PasswordDetailsViewControllerDelegate in order to
+// test the delegate methods are called correctly.
+@interface FakePasswordDetailsDelegate
+    : NSObject <PasswordDetailsViewControllerDelegate>
+@end
+
+@implementation FakePasswordDetailsDelegate
+
+- (void)passwordDetailsViewController:
+            (PasswordDetailsViewController*)viewController
+               didEditPasswordDetails:(PasswordDetails*)password {
+}
+
+@end
+
+// Unit tests for PasswordIssuesTableViewController.
+class PasswordDetailsViewControllerTest : public ChromeTableViewControllerTest {
+ protected:
+  PasswordDetailsViewControllerTest() {
+    handler_ = [[FakePasswordDetailsHandler alloc] init];
+    delegate_ = [[FakePasswordDetailsDelegate alloc] init];
+  }
+
+  ChromeTableViewController* InstantiateController() override {
+    PasswordDetailsViewController* controller =
+        [[PasswordDetailsViewController alloc]
+            initWithStyle:UITableViewStylePlain];
+    controller.handler = handler_;
+    controller.delegate = delegate_;
+    return controller;
+  }
+
+  void ShowPassword() {
+    auto form = autofill::PasswordForm();
+    form.url = GURL("http://www.example.com/");
+    form.action = GURL("http://www.example.com/accounts/Login");
+    form.username_element = base::ASCIIToUTF16("Email");
+    form.username_value = base::ASCIIToUTF16("test@egmail.com");
+    form.password_element = base::ASCIIToUTF16("Passwd");
+    form.password_value = base::ASCIIToUTF16("test");
+    form.submit_element = base::ASCIIToUTF16("signIn");
+    form.signon_realm = "http://www.example.com/";
+    form.scheme = autofill::PasswordForm::Scheme::kHtml;
+    PasswordDetails* password =
+        [[PasswordDetails alloc] initWithPasswordForm:form];
+
+    PasswordDetailsViewController* passwords_controller =
+        static_cast<PasswordDetailsViewController*>(controller());
+    [passwords_controller setPassword:password];
+  }
+
+  void CheckEditCellText(NSString* expected_text, int section, int item) {
+    TableViewTextEditItem* cell =
+        static_cast<TableViewTextEditItem*>(GetTableViewItem(section, item));
+    EXPECT_NSEQ(expected_text, cell.textFieldValue);
+  }
+
+  FakePasswordDetailsHandler* handler() { return handler_; }
+  FakePasswordDetailsDelegate* delegate() { return delegate_; }
+
+ private:
+  FakePasswordDetailsHandler* handler_;
+  FakePasswordDetailsDelegate* delegate_;
+};
+
+// Tests PasswordDetailsViewController is set up with appropriate items
+// and sections.
+TEST_F(PasswordDetailsViewControllerTest, TestModel) {
+  CreateController();
+  CheckController();
+  EXPECT_EQ(1, NumberOfSections());
+
+  EXPECT_EQ(3, NumberOfItemsInSection(0));
+}
+
+// Tests that password is displayed properly.
+TEST_F(PasswordDetailsViewControllerTest, TestPassword) {
+  ShowPassword();
+  EXPECT_EQ(1, NumberOfSections());
+  EXPECT_EQ(3, NumberOfItemsInSection(0));
+
+  EXPECT_NSEQ(@"example.com", controller().title);
+  CheckEditCellText(@"http://www.example.com/", 0, 0);
+  CheckEditCellText(@"test@egmail.com", 0, 1);
+  CheckEditCellText(kMaskedPassword, 0, 2);
+}
diff --git a/ios/chrome/browser/web/forms_egtest.mm b/ios/chrome/browser/web/forms_egtest.mm
index 0662de1d..e8e61a99 100644
--- a/ios/chrome/browser/web/forms_egtest.mm
+++ b/ios/chrome/browser/web/forms_egtest.mm
@@ -528,7 +528,8 @@
 // Tests that submitting a POST-based form by tapping the 'Go' button on the
 // keyboard navigates to the correct URL and the back button works as expected
 // afterwards.
-- (void)testPostFormEntryWithKeyboard {
+// TODO(crbug.com/1106741): reenable this test.
+- (void)DISABLED_testPostFormEntryWithKeyboard {
   // Test fails on iPad Air 2 13.4 crbug.com/1102608.
   if ([ChromeEarlGrey isIPadIdiom] && base::ios::IsRunningOnOrLater(13, 0, 0)) {
     EARL_GREY_TEST_DISABLED(@"Fails in iOS 13 on iPads.");
diff --git a/ios/chrome/browser/web/tab_order_egtest.mm b/ios/chrome/browser/web/tab_order_egtest.mm
index 96ecdae..ebbb0184 100644
--- a/ios/chrome/browser/web/tab_order_egtest.mm
+++ b/ios/chrome/browser/web/tab_order_egtest.mm
@@ -47,7 +47,8 @@
 @implementation TabOrderTestCase
 
 // Tests that new tabs are always inserted after their parent tab.
-- (void)testChildTabOrdering {
+// TODO(crbug.com/1106739): reenable this test.
+- (void)DISABLED_testChildTabOrdering {
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
   const GURL URL1 = self.testServer->GetURL(kLinksTestURL1);
 
diff --git a/ios/chrome/browser/window_activities/window_activity_helpers.h b/ios/chrome/browser/window_activities/window_activity_helpers.h
index 5e81fcfd..27d69f5 100644
--- a/ios/chrome/browser/window_activities/window_activity_helpers.h
+++ b/ios/chrome/browser/window_activities/window_activity_helpers.h
@@ -41,10 +41,6 @@
 // Helper functions to create NSUserActivity instances that encode specific
 // actions in the browser, and to decode those actions from those activities.
 
-// Create a new activity that opens a new, empty tab. |in_incognito| indicates
-// if the new tab should be incognito.
-NSUserActivity* ActivityToOpenNewTab(bool in_incognito);
-
 // Create a new activity that opens a new tab, loading |url| with the referrer
 // |referrer|. |in_incognito| indicates if the new tab should be incognito.
 NSUserActivity* ActivityToLoadURL(WindowActivityOrigin origin,
@@ -64,6 +60,10 @@
 // new tab page in a new tab).
 bool ActivityIsURLLoad(NSUserActivity* activity);
 
+// true if |activity| is one that indicates a URL load (including loading the
+// new tab page in a new tab) in normal mode.
+bool ActivityIsURLLoadInNormalMode(NSUserActivity* activity);
+
 // true if |activity| is one that indicates a tab move.
 bool ActivityIsTabMove(NSUserActivity* activity);
 
diff --git a/ios/chrome/browser/window_activities/window_activity_helpers.mm b/ios/chrome/browser/window_activities/window_activity_helpers.mm
index 3430e920..22a8a1d 100644
--- a/ios/chrome/browser/window_activities/window_activity_helpers.mm
+++ b/ios/chrome/browser/window_activities/window_activity_helpers.mm
@@ -38,14 +38,6 @@
 
 }  // namespace
 
-NSUserActivity* ActivityToOpenNewTab(bool in_incognito) {
-  NSUserActivity* activity = BaseActivityForURLOpening(in_incognito);
-  [activity addUserInfoEntriesFromDictionary:@{
-    kURLKey : net::NSURLWithGURL(GURL(kChromeUINewTabURL))
-  }];
-  return activity;
-}
-
 NSUserActivity* ActivityToLoadURL(WindowActivityOrigin origin,
                                   const GURL& url,
                                   const web::Referrer& referrer,
@@ -88,6 +80,10 @@
          [activity.activityType isEqualToString:kLoadIncognitoURLActivityType];
 }
 
+bool ActivityIsURLLoadInNormalMode(NSUserActivity* activity) {
+  return [activity.activityType isEqualToString:kLoadURLActivityType];
+}
+
 bool ActivityIsTabMove(NSUserActivity* activity) {
   return [activity.activityType isEqualToString:kMoveTabActivityType];
 }
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 81103ec..8cc4541 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -299,6 +299,7 @@
     "//ios/chrome/browser/ui/settings/credit_card_scanner:unit_tests",
     "//ios/chrome/browser/ui/settings/language:unit_tests",
     "//ios/chrome/browser/ui/settings/password:unit_tests",
+    "//ios/chrome/browser/ui/settings/password/password_details:unit_tests",
     "//ios/chrome/browser/ui/settings/privacy:unit_tests",
     "//ios/chrome/browser/ui/settings/sync:unit_tests",
     "//ios/chrome/browser/ui/side_swipe:unit_tests",
diff --git a/media/base/audio_renderer_mixer_input.cc b/media/base/audio_renderer_mixer_input.cc
index b8b0024..578cdca 100644
--- a/media/base/audio_renderer_mixer_input.cc
+++ b/media/base/audio_renderer_mixer_input.cc
@@ -24,11 +24,11 @@
 
 AudioRendererMixerInput::AudioRendererMixerInput(
     AudioRendererMixerPool* mixer_pool,
-    int owner_id,
+    const base::UnguessableToken& owner_token,
     const std::string& device_id,
     AudioLatency::LatencyType latency)
     : mixer_pool_(mixer_pool),
-      owner_id_(owner_id),
+      owner_token_(owner_token),
       device_id_(device_id),
       latency_(latency) {
   DCHECK(mixer_pool_);
@@ -77,7 +77,7 @@
   DCHECK_EQ(device_info_->device_status(), OUTPUT_DEVICE_STATUS_OK);
 
   started_ = true;
-  mixer_ = mixer_pool_->GetMixer(owner_id_, params_, latency_, *device_info_,
+  mixer_ = mixer_pool_->GetMixer(owner_token_, params_, latency_, *device_info_,
                                  std::move(sink_));
 
   // Note: OnRenderError() may be called immediately after this call returns.
@@ -153,7 +153,7 @@
   device_info_.reset();
 
   // If we don't have a sink yet start the process of getting one.
-  sink_ = mixer_pool_->GetSink(owner_id_, device_id_);
+  sink_ = mixer_pool_->GetSink(owner_token_, device_id_);
 
   // Retain a ref to this sink to ensure it is not destructed while this occurs.
   // The callback is guaranteed to execute on this thread, so there are no
@@ -200,7 +200,7 @@
   // Request a new sink using the new device id. This process may fail, so to
   // avoid interrupting working audio, don't set any class variables until we
   // know it's a success.
-  auto new_sink = mixer_pool_->GetSink(owner_id_, device_id);
+  auto new_sink = mixer_pool_->GetSink(owner_token_, device_id);
 
   // Retain a ref to this sink to ensure it is not destructed while this occurs.
   // The callback is guaranteed to execute on this thread, so there are no
diff --git a/media/base/audio_renderer_mixer_input.h b/media/base/audio_renderer_mixer_input.h
index 5368185..c56e1f2 100644
--- a/media/base/audio_renderer_mixer_input.h
+++ b/media/base/audio_renderer_mixer_input.h
@@ -22,6 +22,7 @@
 #include "base/macros.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
+#include "base/unguessable_token.h"
 #include "media/base/audio_converter.h"
 #include "media/base/audio_latency.h"
 #include "media/base/audio_renderer_sink.h"
@@ -36,7 +37,7 @@
       public AudioConverter::InputCallback {
  public:
   AudioRendererMixerInput(AudioRendererMixerPool* mixer_pool,
-                          int owner_id,
+                          const base::UnguessableToken& owner_token,
                           const std::string& device_id,
                           AudioLatency::LatencyType latency);
 
@@ -105,7 +106,7 @@
   // AudioParameters received during Initialize().
   AudioParameters params_;
 
-  const int owner_id_;
+  const base::UnguessableToken owner_token_;
   std::string device_id_;  // ID of hardware device to use
   const AudioLatency::LatencyType latency_;
 
diff --git a/media/base/audio_renderer_mixer_input_unittest.cc b/media/base/audio_renderer_mixer_input_unittest.cc
index 39b9c75..3cfb45f9d 100644
--- a/media/base/audio_renderer_mixer_input_unittest.cc
+++ b/media/base/audio_renderer_mixer_input_unittest.cc
@@ -25,7 +25,8 @@
 
 static const int kSampleRate = 48000;
 static const int kBufferSize = 8192;
-static const int kRenderFrameId = 42;
+static const base::UnguessableToken kFrameToken =
+    base::UnguessableToken::Create();
 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
 static const char kDefaultDeviceId[] = "default";
 static const char kAnotherDeviceId[] = "another";
@@ -46,13 +47,13 @@
   }
 
   void CreateMixerInput(const std::string& device_id) {
-    mixer_input_ = new AudioRendererMixerInput(this, kRenderFrameId, device_id,
+    mixer_input_ = new AudioRendererMixerInput(this, kFrameToken, device_id,
                                                AudioLatency::LATENCY_PLAYBACK);
     mixer_input_->GetOutputDeviceInfoAsync(base::DoNothing());
     task_environment_.RunUntilIdle();
   }
 
-  AudioRendererMixer* GetMixer(int owner_id,
+  AudioRendererMixer* GetMixer(const base::UnguessableToken& owner_token,
                                const AudioParameters& params,
                                AudioLatency::LatencyType latency,
                                const OutputDeviceInfo& sink_info,
@@ -75,7 +76,7 @@
   }
 
   scoped_refptr<AudioRendererSink> GetSink(
-      int owner_id,
+      const base::UnguessableToken& owner_token,
       const std::string& device_id) override {
     OutputDeviceStatus status = OUTPUT_DEVICE_STATUS_OK;
     if (device_id == kNonexistentDeviceId)
@@ -331,7 +332,7 @@
 TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceBeforeGODIA) {
   mixer_input_->Stop();
   mixer_input_ = new AudioRendererMixerInput(
-      this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+      this, kFrameToken, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
 
   base::RunLoop run_loop;
   EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
@@ -348,7 +349,7 @@
 TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceDuringGODIA) {
   mixer_input_->Stop();
   mixer_input_ = new AudioRendererMixerInput(
-      this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+      this, kFrameToken, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
 
   mixer_input_->GetOutputDeviceInfoAsync(
       base::BindOnce(&AudioRendererMixerInputTest::OnDeviceInfoReceived,
@@ -378,7 +379,7 @@
 TEST_F(AudioRendererMixerInputTest, GODIADuringSwitchOutputDevice) {
   mixer_input_->Stop();
   mixer_input_ = new AudioRendererMixerInput(
-      this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+      this, kFrameToken, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
 
   mixer_input_->SwitchOutputDevice(
       kAnotherDeviceId,
@@ -409,7 +410,7 @@
 TEST_F(AudioRendererMixerInputTest, GODIADuringSwitchOutputDeviceWhichFails) {
   mixer_input_->Stop();
   mixer_input_ = new AudioRendererMixerInput(
-      this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+      this, kFrameToken, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
 
   mixer_input_->SwitchOutputDevice(
       kNonexistentDeviceId,
diff --git a/media/base/audio_renderer_mixer_pool.h b/media/base/audio_renderer_mixer_pool.h
index 461960d..8562d588 100644
--- a/media/base/audio_renderer_mixer_pool.h
+++ b/media/base/audio_renderer_mixer_pool.h
@@ -10,6 +10,10 @@
 #include "media/base/audio_latency.h"
 #include "media/base/output_device_info.h"
 
+namespace base {
+class UnguessableToken;
+}  // namespace base
+
 namespace media {
 class AudioParameters;
 class AudioRendererMixer;
@@ -31,7 +35,7 @@
   // GetOutputDeviceInfoAsync() on |sink| to get |sink_info|, and it must have
   // a device_status() == OUTPUT_DEVICE_STATUS_OK.
   virtual AudioRendererMixer* GetMixer(
-      int owner_id,
+      const base::UnguessableToken& owner_token,
       const AudioParameters& input_params,
       AudioLatency::LatencyType latency,
       const OutputDeviceInfo& sink_info,
@@ -44,7 +48,7 @@
   // Returns an AudioRendererSink for use with GetMixer(). Inputs must call this
   // to get a sink to use with a subsequent GetMixer()
   virtual scoped_refptr<AudioRendererSink> GetSink(
-      int owner_id,
+      const base::UnguessableToken& owner_token,
       const std::string& device_id) = 0;
 
  private:
diff --git a/media/base/audio_renderer_mixer_unittest.cc b/media/base/audio_renderer_mixer_unittest.cc
index d979c59..7b195f5 100644
--- a/media/base/audio_renderer_mixer_unittest.cc
+++ b/media/base/audio_renderer_mixer_unittest.cc
@@ -86,7 +86,7 @@
         new FakeAudioRenderCallback(step, output_parameters_.sample_rate()));
   }
 
-  AudioRendererMixer* GetMixer(int owner_id,
+  AudioRendererMixer* GetMixer(const base::UnguessableToken& owner_token,
                                const AudioParameters& params,
                                AudioLatency::LatencyType latency,
                                const OutputDeviceInfo& sink_info,
@@ -99,7 +99,7 @@
   }
 
   scoped_refptr<AudioRendererSink> GetSink(
-      int owner_id,
+      const base::UnguessableToken& owner_token,
       const std::string& device_id) override {
     return sink_;
   }
@@ -334,9 +334,9 @@
 
   scoped_refptr<AudioRendererMixerInput> CreateMixerInput() {
     auto input = base::MakeRefCounted<AudioRendererMixerInput>(
-        this,
-        // Zero frame id, default device ID.
-        0, std::string(), AudioLatency::LATENCY_PLAYBACK);
+        this, base::UnguessableToken::Create(),
+        // default device ID.
+        std::string(), AudioLatency::LATENCY_PLAYBACK);
     input->GetOutputDeviceInfoAsync(
         base::DoNothing());  // Primes input, needed for tests.
     task_env_.RunUntilIdle();
diff --git a/media/blink/video_frame_compositor.cc b/media/blink/video_frame_compositor.cc
index 2b3816c8..e0294a70c 100644
--- a/media/blink/video_frame_compositor.cc
+++ b/media/blink/video_frame_compositor.cc
@@ -33,13 +33,13 @@
       background_rendering_timer_(
           FROM_HERE,
           base::TimeDelta::FromMilliseconds(kBackgroundRenderingTimeoutMs),
-          base::Bind(&VideoFrameCompositor::BackgroundRender,
-                     base::Unretained(this))),
+          base::BindRepeating(&VideoFrameCompositor::BackgroundRender,
+                              base::Unretained(this))),
       force_begin_frames_timer_(
           FROM_HERE,
           base::TimeDelta::FromMilliseconds(kForceBeginFramesTimeoutMs),
-          base::Bind(&VideoFrameCompositor::StopForceBeginFrames,
-                     base::Unretained(this))),
+          base::BindRepeating(&VideoFrameCompositor::StopForceBeginFrames,
+                              base::Unretained(this))),
       submitter_(std::move(submitter)) {
   if (submitter_) {
     task_runner_->PostTask(
diff --git a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java
index 9b910da..a6e84cc 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java
@@ -7,41 +7,38 @@
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 
-import androidx.annotation.GuardedBy;
-
-import org.junit.rules.TestWatcher;
+import org.junit.rules.TestRule;
 import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
 
 /**
  * Junit4 rule for starting embedded test server when necessary (i.e. when accessed via
  * {@link #getServer()}), and shutting it down when the test finishes.
  */
-public class EmbeddedTestServerRule extends TestWatcher {
-    private final Object mLock = new Object();
-    @GuardedBy("mLock")
+public class EmbeddedTestServerRule implements TestRule {
     private EmbeddedTestServer mServer;
 
     // The default value of 0 will result in the same behavior as createAndStartServer
     // (auto-selected port).
-    @GuardedBy("mLock")
     private int mServerPort;
 
-    @GuardedBy("mLock")
     private boolean mUseHttps;
 
-    @GuardedBy("mLock")
     @ServerCertificate
     private int mCertificateType = ServerCertificate.CERT_OK;
 
     @Override
-    protected void finished(Description description) {
-        super.finished(description);
-        synchronized (mLock) {
-            if (mServer != null) {
-                mServer.stopAndDestroyServer();
-                mServer = null;
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                try {
+                    base.evaluate();
+                } finally {
+                    if (mServer != null) mServer.stopAndDestroyServer();
+                }
             }
-        }
+        };
     }
 
     /**
@@ -50,16 +47,14 @@
      * @return the test server.
      */
     public EmbeddedTestServer getServer() {
-        synchronized (mLock) {
-            if (mServer == null) {
-                Context context = InstrumentationRegistry.getContext();
-                mServer = mUseHttps
-                        ? EmbeddedTestServer.createAndStartHTTPSServerWithPort(
-                                context, mCertificateType, mServerPort)
-                        : EmbeddedTestServer.createAndStartServerWithPort(context, mServerPort);
-            }
-            return mServer;
+        if (mServer == null) {
+            Context context = InstrumentationRegistry.getContext();
+            mServer = mUseHttps
+                    ? EmbeddedTestServer.createAndStartHTTPSServerWithPort(
+                            context, mCertificateType, mServerPort)
+                    : EmbeddedTestServer.createAndStartServerWithPort(context, mServerPort);
         }
+        return mServer;
     }
 
     public String getOrigin() {
@@ -73,25 +68,19 @@
      * @param port the port to start the server with, or 0 for an automatically selected one.
      */
     public void setServerPort(int port) {
-        synchronized (mLock) {
-            assert mServer == null;
-            mServerPort = port;
-        }
+        assert mServer == null;
+        mServerPort = port;
     }
 
     /** Sets whether to create an HTTPS (vs HTTP) server. */
     public void setServerUsesHttps(boolean useHttps) {
-        synchronized (mLock) {
-            assert mServer == null;
-            mUseHttps = useHttps;
-        }
+        assert mServer == null;
+        mUseHttps = useHttps;
     }
 
     /** Sets what type of certificate the server uses when running as an HTTPS server. */
     public void setCertificateType(@ServerCertificate int certificateType) {
-        synchronized (mLock) {
-            assert mServer == null;
-            mCertificateType = certificateType;
-        }
+        assert mServer == null;
+        mCertificateType = certificateType;
     }
 }
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index a48dd9a..72f6e7c 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -40,6 +40,7 @@
 #include "ppapi/cpp/dev/memory_dev.h"
 #include "ppapi/cpp/dev/text_input_dev.h"
 #include "ppapi/cpp/dev/url_util_dev.h"
+#include "ppapi/cpp/graphics_2d.h"
 #include "ppapi/cpp/image_data.h"
 #include "ppapi/cpp/input_event.h"
 #include "ppapi/cpp/module.h"
@@ -47,6 +48,7 @@
 #include "ppapi/cpp/private/pdf.h"
 #include "ppapi/cpp/rect.h"
 #include "ppapi/cpp/resource.h"
+#include "ppapi/cpp/size.h"
 #include "ppapi/cpp/url_request_info.h"
 #include "ppapi/cpp/var_array.h"
 #include "ppapi/cpp/var_array_buffer.h"
@@ -446,7 +448,7 @@
     : pp::Instance(instance),
       pp::Find_Private(this),
       pp::Printing_Dev(this),
-      paint_manager_(this, this) {
+      paint_manager_(this) {
   callback_factory_.Initialize(this);
   pp::Module::Get()->AddPluginInterface(kPPPPdfInterface, &ppp_private);
   AddPerInstanceObject(kPPPPdfInterface, this);
@@ -948,6 +950,14 @@
   SetTickmarks(tickmarks_);
 }
 
+pp::Graphics2D OutOfProcessInstance::CreatePaintGraphics(const pp::Size& size) {
+  return pp::Graphics2D(this, size, /*is_always_opaque=*/true);
+}
+
+bool OutOfProcessInstance::BindPaintGraphics(pp::Graphics2D& graphics) {
+  return BindGraphics(graphics);
+}
+
 void OutOfProcessInstance::OnPaint(const std::vector<pp::Rect>& paint_rects,
                                    std::vector<PaintReadyRect>* ready,
                                    std::vector<pp::Rect>* pending) {
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h
index 3a0fdcd..b6b05e9a 100644
--- a/pdf/out_of_process_instance.h
+++ b/pdf/out_of_process_instance.h
@@ -30,6 +30,8 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 
 namespace pp {
+class Graphics2D;
+class Size;
 class TextInput_Dev;
 }
 
@@ -60,6 +62,8 @@
   void StopFind() override;
 
   // pp::PaintManager::Client implementation.
+  pp::Graphics2D CreatePaintGraphics(const pp::Size& size) override;
+  bool BindPaintGraphics(pp::Graphics2D& graphics) override;
   void OnPaint(const std::vector<pp::Rect>& paint_rects,
                std::vector<PaintReadyRect>* ready,
                std::vector<pp::Rect>* pending) override;
diff --git a/pdf/paint_manager.cc b/pdf/paint_manager.cc
index 8f61e99..2d07ef2 100644
--- a/pdf/paint_manager.cc
+++ b/pdf/paint_manager.cc
@@ -13,14 +13,11 @@
 #include "base/check_op.h"
 #include "pdf/paint_ready_rect.h"
 #include "ppapi/c/pp_errors.h"
-#include "ppapi/cpp/instance.h"
 #include "ppapi/cpp/module.h"
 
 namespace chrome_pdf {
 
-PaintManager::PaintManager(pp::Instance* instance, Client* client)
-    : instance_(instance), client_(client) {
-  DCHECK(instance_);
+PaintManager::PaintManager(Client* client) : client_(client) {
   DCHECK(client_);
 
   // Set the callback object outside of the initializer list to avoid a
@@ -184,8 +181,7 @@
     // we only resize by a small amount.
     pp::Size new_size = GetNewContextSize(graphics_.size(), pending_size_);
     if (graphics_.size() != new_size) {
-      graphics_ =
-          pp::Graphics2D(instance_, new_size, /*is_always_opaque=*/true);
+      graphics_ = client_->CreatePaintGraphics(new_size);
       graphics_need_to_be_bound_ = true;
 
       // Since we're binding a new one, all of the callbacks have been canceled.
@@ -258,7 +254,7 @@
   first_paint_ = false;
 
   if (graphics_need_to_be_bound_) {
-    instance_->BindGraphics(graphics_);
+    client_->BindPaintGraphics(graphics_);
     graphics_need_to_be_bound_ = false;
   }
 }
diff --git a/pdf/paint_manager.h b/pdf/paint_manager.h
index 3160864..03c2e6382 100644
--- a/pdf/paint_manager.h
+++ b/pdf/paint_manager.h
@@ -14,9 +14,9 @@
 #include "ppapi/utility/completion_callback_factory.h"
 
 namespace pp {
-class Instance;
 class Point;
 class Rect;
+class Size;
 }  // namespace pp
 
 namespace chrome_pdf {
@@ -32,6 +32,14 @@
  public:
   class Client {
    public:
+    // Creates a new, unbound `pp::Graphics2D` for the paint manager, with the
+    // given |size| and always-opaque rendering.
+    virtual pp::Graphics2D CreatePaintGraphics(const pp::Size& size) = 0;
+
+    // Binds a `pp::Graphics2D` created by `CreatePaintGraphics()`, returning
+    // `true` if binding was successful.
+    virtual bool BindPaintGraphics(pp::Graphics2D& graphics) = 0;
+
     // Paints the given invalid area of the plugin to the given graphics
     // device. Returns true if anything was painted.
     //
@@ -56,20 +64,15 @@
 
    protected:
     // You shouldn't be doing deleting through this interface.
-    virtual ~Client() {}
+    ~Client() = default;
   };
 
-  // The instance is the plugin instance using this paint manager to do its
-  // painting. Painting will automatically go to this instance and you don't
-  // have to manually bind any device context (this is all handled by the
-  // paint manager).
-  //
   // The Client is a non-owning pointer and must remain valid (normally the
   // object implementing the Client interface will own the paint manager).
   //
   // You will need to call SetSize before this class will do anything. Normally
   // you do this from the ViewChanged method of your plugin instance.
-  PaintManager(pp::Instance* instance, Client* client);
+  explicit PaintManager(Client* client);
   PaintManager(const PaintManager&) = delete;
   PaintManager& operator=(const PaintManager&) = delete;
   ~PaintManager();
@@ -140,8 +143,6 @@
   // pending.
   void OnManualCallbackComplete(int32_t);
 
-  pp::Instance* const instance_;
-
   // Non-owning pointer. See the constructor.
   Client* const client_;
 
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
index 75d54c2..e31c2f1 100644
--- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
+++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
@@ -122,6 +122,19 @@
   // Marks the given SurfaceIds for destruction.
   EvictSurfaces(array<SurfaceId> surface_ids);
 
+  // Starts throttling the frame sinks specified by |frame_sink_ids| and all
+  // their descendant sinks to send BeginFrames at an interval of |interval|.
+  // |interval| should be greater than zero. Calling this function before
+  // calling EndThrottling() to end a previous throttling operation will
+  // automatically end the previous operation before applying the current
+  // throttling operation.
+  StartThrottling(
+      array<FrameSinkId> frame_sink_ids,
+      mojo_base.mojom.TimeDelta interval);
+
+  // Ends all previously throttled frame sinks.
+  EndThrottling();
+
   // Takes a snapshot of |surface_id| or a newer surface with the same
   // FrameSinkId. The request will be queued up until such surface exists and is
   // reachable from the root surface.
diff --git a/third_party/abseil-cpp/CMakeLists.txt b/third_party/abseil-cpp/CMakeLists.txt
index 4d10710e..54ce499 100644
--- a/third_party/abseil-cpp/CMakeLists.txt
+++ b/third_party/abseil-cpp/CMakeLists.txt
@@ -30,6 +30,9 @@
 # Project version variables are the empty string if version is unspecified
 cmake_policy(SET CMP0048 NEW)
 
+# option() honor variables
+cmake_policy(SET CMP0077 NEW)
+
 project(absl CXX)
 
 # Output directory is correct by default for most build setups. However, when
@@ -41,9 +44,9 @@
 # when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp))
 # in the source tree of a project that uses it, install rules are disabled.
 if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
-  set(ABSL_ENABLE_INSTALL FALSE)
+  option(ABSL_ENABLE_INSTALL "Enable install rule" OFF)
 else()
-  set(ABSL_ENABLE_INSTALL TRUE)
+  option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
 endif()
 
 list(APPEND CMAKE_MODULE_PATH
@@ -98,7 +101,6 @@
   # enable CTest.  This will set BUILD_TESTING to ON unless otherwise specified
   # on the command line
   include(CTest)
-  enable_testing()
 
   ## check targets
   if (NOT ABSL_USE_EXTERNAL_GOOGLETEST)
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium
index f6db166d..0de30c70 100644
--- a/third_party/abseil-cpp/README.chromium
+++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@
 License: Apache 2.0
 License File: LICENSE
 Version: 0
-Revision: 23f1f9cf6d02f834d55c0595566c0d607d4c5ed8
+Revision: f624790b7f76ab92fed5ae966abb99a0d455c96f
 Security Critical: yes
 
 Description:
diff --git a/third_party/abseil-cpp/WORKSPACE b/third_party/abseil-cpp/WORKSPACE
index 1a1da6c..9633819 100644
--- a/third_party/abseil-cpp/WORKSPACE
+++ b/third_party/abseil-cpp/WORKSPACE
@@ -20,9 +20,9 @@
 # GoogleTest/GoogleMock framework. Used by most unit-tests.
 http_archive(
     name = "com_google_googletest",
-    urls = ["https://github.com/google/googletest/archive/011959aafddcd30611003de96cfd8d7a7685c700.zip"],  # 2020-05-14T00:36:05Z
-    strip_prefix = "googletest-011959aafddcd30611003de96cfd8d7a7685c700",
-    sha256 = "6a5d7d63cd6e0ad2a7130471105a3b83799a7a2b14ef7ec8d742b54f01a4833c",
+    urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"],  # 2020-06-12T22:24:28Z
+    strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b",
+    sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48",
 )
 
 # Google benchmark.
diff --git a/third_party/abseil-cpp/absl/BUILD.bazel b/third_party/abseil-cpp/absl/BUILD.bazel
index f7fc2a7..1019ab5e 100644
--- a/third_party/abseil-cpp/absl/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/BUILD.bazel
@@ -58,3 +58,11 @@
     },
     visibility = [":__subpackages__"],
 )
+
+config_setting(
+    name = "wasm",
+    values = {
+        "cpu": "wasm32",
+    },
+    visibility = [":__subpackages__"],
+)
diff --git a/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel
index 745a598..23f2763 100644
--- a/third_party/abseil-cpp/absl/base/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/base/BUILD.bazel
@@ -161,6 +161,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     visibility = [
@@ -222,6 +223,7 @@
         "//absl:windows": [
             "-DEFAULTLIB:advapi32.lib",
         ],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
diff --git a/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h b/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h
index ed0b4bf..6ef79fb 100644
--- a/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h
+++ b/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h
@@ -18,6 +18,7 @@
 #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
 #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
 
+#include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/scheduling_mode.h"
 #include "absl/base/macros.h"
 
@@ -29,6 +30,13 @@
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
+class CondVar;
+class Mutex;
+
+namespace synchronization_internal {
+int MutexDelay(int32_t c, int mode);
+}  // namespace synchronization_internal
+
 namespace base_internal {
 
 class SchedulingHelper;  // To allow use of SchedulingGuard.
@@ -76,9 +84,23 @@
     bool disabled;
   };
 
+  // A scoped helper to enable rescheduling temporarily.
+  // REQUIRES: destructor must run in same thread as constructor.
+  class ScopedEnable {
+   public:
+    ScopedEnable();
+    ~ScopedEnable();
+
+   private:
+    int scheduling_disabled_depth_;
+  };
+
   // Access to SchedulingGuard is explicitly permitted.
+  friend class absl::CondVar;
+  friend class absl::Mutex;
   friend class SchedulingHelper;
   friend class SpinLock;
+  friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
 
   SchedulingGuard(const SchedulingGuard&) = delete;
   SchedulingGuard& operator=(const SchedulingGuard&) = delete;
@@ -100,6 +122,12 @@
   return;
 }
 
+inline SchedulingGuard::ScopedEnable::ScopedEnable()
+    : scheduling_disabled_depth_(0) {}
+inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
+  ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
+}
+
 }  // namespace base_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc b/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc
index 624d5b9..46a6f74 100644
--- a/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc
@@ -75,7 +75,7 @@
   // - If a thread implementation chooses to recycle threads, that
   //   correct re-initialization occurs.
   static const int kNumLoops = 3;
-  static const int kNumThreads = 400;
+  static const int kNumThreads = 32;
   for (int iter = 0; iter < kNumLoops; iter++) {
     std::vector<std::thread> threads;
     for (int i = 0; i < kNumThreads; ++i) {
diff --git a/third_party/abseil-cpp/absl/base/thread_annotations.h b/third_party/abseil-cpp/absl/base/thread_annotations.h
index 0c207e0..86e0ffb8 100644
--- a/third_party/abseil-cpp/absl/base/thread_annotations.h
+++ b/third_party/abseil-cpp/absl/base/thread_annotations.h
@@ -37,12 +37,6 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 
-#if defined(__clang__)
-#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
-#else
-#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x)  // no-op
-#endif
-
 // ABSL_GUARDED_BY()
 //
 // Documents if a shared field or global variable needs to be protected by a
@@ -60,8 +54,11 @@
 //     int p1_ ABSL_GUARDED_BY(mu_);
 //     ...
 //   };
-#define ABSL_GUARDED_BY(x) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x))
+#if ABSL_HAVE_ATTRIBUTE(guarded_by)
+#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))
+#else
+#define ABSL_GUARDED_BY(x)
+#endif
 
 // ABSL_PT_GUARDED_BY()
 //
@@ -83,8 +80,11 @@
 //   // `q_`, guarded by `mu1_`, points to a shared memory location that is
 //   // guarded by `mu2_`:
 //   int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_);
-#define ABSL_PT_GUARDED_BY(x) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x))
+#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by)
+#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
+#else
+#define ABSL_PT_GUARDED_BY(x)
+#endif
 
 // ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()
 //
@@ -101,11 +101,17 @@
 //
 //   Mutex m1_;
 //   Mutex m2_ ABSL_ACQUIRED_AFTER(m1_);
-#define ABSL_ACQUIRED_AFTER(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(acquired_after)
+#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
+#else
+#define ABSL_ACQUIRED_AFTER(...)
+#endif
 
-#define ABSL_ACQUIRED_BEFORE(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(acquired_before)
+#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
+#else
+#define ABSL_ACQUIRED_BEFORE(...)
+#endif
 
 // ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()
 //
@@ -130,20 +136,30 @@
 //
 //   void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
 //   void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
-#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)   \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      exclusive_locks_required(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required)
+#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
+  __attribute__((exclusive_locks_required(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
+#endif
 
+#if ABSL_HAVE_ATTRIBUTE(shared_locks_required)
 #define ABSL_SHARED_LOCKS_REQUIRED(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__))
+  __attribute__((shared_locks_required(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_LOCKS_REQUIRED(...)
+#endif
 
 // ABSL_LOCKS_EXCLUDED()
 //
 // Documents the locks acquired in the body of the function. These locks
 // cannot be held when calling this function (as Abseil's `Mutex` locks are
 // non-reentrant).
-#define ABSL_LOCKS_EXCLUDED(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
+#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
+#else
+#define ABSL_LOCKS_EXCLUDED(...)
+#endif
 
 // ABSL_LOCK_RETURNED()
 //
@@ -151,8 +167,7 @@
 // a public getter method that returns a pointer to a private mutex should
 // be annotated with ABSL_LOCK_RETURNED.
 #if ABSL_HAVE_ATTRIBUTE(lock_returned)
-#define ABSL_LOCK_RETURNED(x) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x))
+#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x)))
 #else
 #define ABSL_LOCK_RETURNED(x)
 #endif
@@ -160,7 +175,11 @@
 // ABSL_LOCKABLE
 //
 // Documents if a class/type is a lockable type (such as the `Mutex` class).
-#define ABSL_LOCKABLE ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable)
+#if ABSL_HAVE_ATTRIBUTE(lockable)
+#define ABSL_LOCKABLE __attribute__((lockable))
+#else
+#define ABSL_LOCKABLE
+#endif
 
 // ABSL_SCOPED_LOCKABLE
 //
@@ -169,30 +188,43 @@
 // acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
 // arguments; the analysis will assume that the destructor unlocks whatever the
 // constructor locked.
-#define ABSL_SCOPED_LOCKABLE \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable)
+#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)
+#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))
+#else
+#define ABSL_SCOPED_LOCKABLE
+#endif
 
 // ABSL_EXCLUSIVE_LOCK_FUNCTION()
 //
 // Documents functions that acquire a lock in the body of a function, and do
 // not release it.
-#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)    \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      exclusive_lock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function)
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
+  __attribute__((exclusive_lock_function(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)
+#endif
 
 // ABSL_SHARED_LOCK_FUNCTION()
 //
 // Documents functions that acquire a shared (reader) lock in the body of a
 // function, and do not release it.
+#if ABSL_HAVE_ATTRIBUTE(shared_lock_function)
 #define ABSL_SHARED_LOCK_FUNCTION(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__))
+  __attribute__((shared_lock_function(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_LOCK_FUNCTION(...)
+#endif
 
 // ABSL_UNLOCK_FUNCTION()
 //
 // Documents functions that expect a lock to be held on entry to the function,
 // and release it in the body of the function.
-#define ABSL_UNLOCK_FUNCTION(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(unlock_function)
+#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
+#else
+#define ABSL_UNLOCK_FUNCTION(...)
+#endif
 
 // ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()
 //
@@ -202,31 +234,49 @@
 // success, or `false` for functions that return `false` on success. The second
 // argument specifies the mutex that is locked on success. If unspecified, this
 // mutex is assumed to be `this`.
+#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function)
 #define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      exclusive_trylock_function(__VA_ARGS__))
+  __attribute__((exclusive_trylock_function(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...)
+#endif
 
-#define ABSL_SHARED_TRYLOCK_FUNCTION(...)    \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      shared_trylock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function)
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
+  __attribute__((shared_trylock_function(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...)
+#endif
 
 // ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK()
 //
 // Documents functions that dynamically check to see if a lock is held, and fail
 // if it is not held.
+#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock)
 #define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_lock(__VA_ARGS__))
+  __attribute__((assert_exclusive_lock(__VA_ARGS__)))
+#else
+#define ABSL_ASSERT_EXCLUSIVE_LOCK(...)
+#endif
 
+#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock)
 #define ABSL_ASSERT_SHARED_LOCK(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__))
+  __attribute__((assert_shared_lock(__VA_ARGS__)))
+#else
+#define ABSL_ASSERT_SHARED_LOCK(...)
+#endif
 
 // ABSL_NO_THREAD_SAFETY_ANALYSIS
 //
 // Turns off thread safety checking within the body of a particular function.
 // This annotation is used to mark functions that are known to be correct, but
 // the locking behavior is more complicated than the analyzer can handle.
+#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis)
 #define ABSL_NO_THREAD_SAFETY_ANALYSIS \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis)
+  __attribute__((no_thread_safety_analysis))
+#else
+#define ABSL_NO_THREAD_SAFETY_ANALYSIS
+#endif
 
 //------------------------------------------------------------------------------
 // Tool-Supplied Annotations
diff --git a/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc b/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
index a5bb009..e5f5929 100644
--- a/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
+++ b/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
@@ -150,8 +150,7 @@
 
 template <typename FixedArrT>
 testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) {
-  // Marked volatile to prevent optimization. Used for running asan tests.
-  volatile int sum = 0;
+  int sum = 0;
   for (const auto& thrower : *fixed_arr) {
     sum += thrower.Get();
   }
diff --git a/third_party/abseil-cpp/absl/debugging/BUILD.bazel b/third_party/abseil-cpp/absl/debugging/BUILD.bazel
index d336246..bdc50e0 100644
--- a/third_party/abseil-cpp/absl/debugging/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/debugging/BUILD.bazel
@@ -148,6 +148,7 @@
     copts = ABSL_TEST_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
diff --git a/third_party/abseil-cpp/absl/flags/reflection.cc b/third_party/abseil-cpp/absl/flags/reflection.cc
index 02b7c06..1b02583 100644
--- a/third_party/abseil-cpp/absl/flags/reflection.cc
+++ b/third_party/abseil-cpp/absl/flags/reflection.cc
@@ -58,10 +58,6 @@
   // Will emit a warning if a 'retired' flag is specified.
   CommandLineFlag* FindFlagLocked(absl::string_view name);
 
-  // Returns the retired flag object for the specified name, or nullptr if not
-  // found or not retired.  Does not emit a warning.
-  CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
-
   static FlagRegistry& GlobalRegistry();  // returns a singleton registry
 
  private:
@@ -88,14 +84,6 @@
   if (i == flags_.end()) {
     return nullptr;
   }
-  return i->second;
-}
-
-CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end() || !i->second->IsRetired()) {
-    return nullptr;
-  }
 
   return i->second;
 }
diff --git a/third_party/abseil-cpp/absl/random/internal/BUILD.bazel b/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
index d81477ff..83843b4 100644
--- a/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
@@ -59,7 +59,10 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = ["//absl/base:config"],
+    deps = [
+        "//absl/base:config",
+        "//absl/meta:type_traits",
+    ],
 )
 
 cc_library(
@@ -96,6 +99,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -319,10 +323,6 @@
         "//absl:windows": [],
         "//conditions:default": ["-Wno-pass-failed"],
     }),
-    # copts in RANDEN_HWAES_COPTS can make this target unusable as a module
-    # leading to a Clang diagnostic. Furthermore, it only has a private header
-    # anyway and thus there wouldn't be any gain from using it as a module.
-    features = ["-header_modules"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":platform",
diff --git a/third_party/abseil-cpp/absl/random/internal/BUILD.gn b/third_party/abseil-cpp/absl/random/internal/BUILD.gn
index 62f67b4..3940946c 100644
--- a/third_party/abseil-cpp/absl/random/internal/BUILD.gn
+++ b/third_party/abseil-cpp/absl/random/internal/BUILD.gn
@@ -20,7 +20,10 @@
 
 absl_source_set("fast_uniform_bits") {
   public = [ "fast_uniform_bits.h" ]
-  deps = [ "//third_party/abseil-cpp/absl/base:config" ]
+  deps = [
+    "//third_party/abseil-cpp/absl/base:config",
+    "//third_party/abseil-cpp/absl/meta:type_traits",
+  ]
 }
 
 absl_source_set("seed_material") {
diff --git a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h
index f13c872..425aaf7 100644
--- a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h
+++ b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h
@@ -21,6 +21,7 @@
 #include <type_traits>
 
 #include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -38,28 +39,17 @@
 template <typename URBG>
 constexpr typename URBG::result_type RangeSize() {
   using result_type = typename URBG::result_type;
+  static_assert((URBG::max)() != (URBG::min)(), "URBG range cannot be 0.");
   return ((URBG::max)() == (std::numeric_limits<result_type>::max)() &&
           (URBG::min)() == std::numeric_limits<result_type>::lowest())
              ? result_type{0}
-             : (URBG::max)() - (URBG::min)() + result_type{1};
-}
-
-template <typename UIntType>
-constexpr UIntType LargestPowerOfTwoLessThanOrEqualTo(UIntType n) {
-  return n < 2 ? n : 2 * LargestPowerOfTwoLessThanOrEqualTo(n / 2);
-}
-
-// Given a URBG generating values in the closed interval [Lo, Hi], returns the
-// largest power of two less than or equal to `Hi - Lo + 1`.
-template <typename URBG>
-constexpr typename URBG::result_type PowerOfTwoSubRangeSize() {
-  return LargestPowerOfTwoLessThanOrEqualTo(RangeSize<URBG>());
+             : ((URBG::max)() - (URBG::min)() + result_type{1});
 }
 
 // Computes the floor of the log. (i.e., std::floor(std::log2(N));
 template <typename UIntType>
 constexpr UIntType IntegerLog2(UIntType n) {
-  return (n <= 1) ? 0 : 1 + IntegerLog2(n / 2);
+  return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1);
 }
 
 // Returns the number of bits of randomness returned through
@@ -68,18 +58,23 @@
 constexpr size_t NumBits() {
   return RangeSize<URBG>() == 0
              ? std::numeric_limits<typename URBG::result_type>::digits
-             : IntegerLog2(PowerOfTwoSubRangeSize<URBG>());
+             : IntegerLog2(RangeSize<URBG>());
 }
 
 // Given a shift value `n`, constructs a mask with exactly the low `n` bits set.
 // If `n == 0`, all bits are set.
 template <typename UIntType>
-constexpr UIntType MaskFromShift(UIntType n) {
+constexpr UIntType MaskFromShift(size_t n) {
   return ((n % std::numeric_limits<UIntType>::digits) == 0)
              ? ~UIntType{0}
              : (UIntType{1} << n) - UIntType{1};
 }
 
+// Tags used to dispatch FastUniformBits::generate to the simple or more complex
+// entropy extraction algorithm.
+struct SimplifiedLoopTag {};
+struct RejectionLoopTag {};
+
 // FastUniformBits implements a fast path to acquire uniform independent bits
 // from a type which conforms to the [rand.req.urbg] concept.
 // Parameterized by:
@@ -107,50 +102,16 @@
                 "Class-template FastUniformBits<> must be parameterized using "
                 "an unsigned type.");
 
-  // PowerOfTwoVariate() generates a single random variate, always returning a
-  // value in the half-open interval `[0, PowerOfTwoSubRangeSize<URBG>())`. If
-  // the URBG already generates values in a power-of-two range, the generator
-  // itself is used. Otherwise, we use rejection sampling on the largest
-  // possible power-of-two-sized subrange.
-  struct PowerOfTwoTag {};
-  struct RejectionSamplingTag {};
-  template <typename URBG>
-  static typename URBG::result_type PowerOfTwoVariate(
-      URBG& g) {  // NOLINT(runtime/references)
-    using tag =
-        typename std::conditional<IsPowerOfTwoOrZero(RangeSize<URBG>()),
-                                  PowerOfTwoTag, RejectionSamplingTag>::type;
-    return PowerOfTwoVariate(g, tag{});
-  }
-
-  template <typename URBG>
-  static typename URBG::result_type PowerOfTwoVariate(
-      URBG& g,  // NOLINT(runtime/references)
-      PowerOfTwoTag) {
-    return g() - (URBG::min)();
-  }
-
-  template <typename URBG>
-  static typename URBG::result_type PowerOfTwoVariate(
-      URBG& g,  // NOLINT(runtime/references)
-      RejectionSamplingTag) {
-    // Use rejection sampling to ensure uniformity across the range.
-    typename URBG::result_type u;
-    do {
-      u = g() - (URBG::min)();
-    } while (u >= PowerOfTwoSubRangeSize<URBG>());
-    return u;
-  }
-
   // Generate() generates a random value, dispatched on whether
-  // the underlying URBG must loop over multiple calls or not.
+  // the underlying URBG must use rejection sampling to generate a value,
+  // or whether a simplified loop will suffice.
   template <typename URBG>
   result_type Generate(URBG& g,  // NOLINT(runtime/references)
-                       std::true_type /* avoid_looping */);
+                       SimplifiedLoopTag);
 
   template <typename URBG>
   result_type Generate(URBG& g,  // NOLINT(runtime/references)
-                       std::false_type /* avoid_looping */);
+                       RejectionLoopTag);
 };
 
 template <typename UIntType>
@@ -162,31 +123,47 @@
   // Y = (2 ^ kRange) - 1
   static_assert((URBG::max)() > (URBG::min)(),
                 "URBG::max and URBG::min may not be equal.");
+
+  using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),
+                                  SimplifiedLoopTag, RejectionLoopTag>;
+  return Generate(g, tag{});
+}
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
+                                    SimplifiedLoopTag) {
+  // The simplified version of FastUniformBits works only on URBGs that have
+  // a range that is a power of 2. In this case we simply loop and shift without
+  // attempting to balance the bits across calls.
+  static_assert(IsPowerOfTwoOrZero(RangeSize<URBG>()),
+                "incorrect Generate tag for URBG instance");
+
+  static constexpr size_t kResultBits =
+      std::numeric_limits<result_type>::digits;
+  static constexpr size_t kUrbgBits = NumBits<URBG>();
+  static constexpr size_t kIters =
+      (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0);
+  static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits;
+  static constexpr auto kMin = (URBG::min)();
+
+  result_type r = static_cast<result_type>(g() - kMin);
+  for (size_t n = 1; n < kIters; ++n) {
+    r = (r << kShift) + static_cast<result_type>(g() - kMin);
+  }
+  return r;
+}
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
+                                    RejectionLoopTag) {
+  static_assert(!IsPowerOfTwoOrZero(RangeSize<URBG>()),
+                "incorrect Generate tag for URBG instance");
   using urbg_result_type = typename URBG::result_type;
-  constexpr urbg_result_type kRangeMask =
-      RangeSize<URBG>() == 0
-          ? (std::numeric_limits<urbg_result_type>::max)()
-          : static_cast<urbg_result_type>(PowerOfTwoSubRangeSize<URBG>() - 1);
-  return Generate(g, std::integral_constant<bool, (kRangeMask >= (max)())>{});
-}
 
-template <typename UIntType>
-template <typename URBG>
-typename FastUniformBits<UIntType>::result_type
-FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
-                                    std::true_type /* avoid_looping */) {
-  // The width of the result_type is less than than the width of the random bits
-  // provided by URBG.  Thus, generate a single value and then simply mask off
-  // the required bits.
-
-  return PowerOfTwoVariate(g) & (max)();
-}
-
-template <typename UIntType>
-template <typename URBG>
-typename FastUniformBits<UIntType>::result_type
-FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
-                                    std::false_type /* avoid_looping */) {
   // See [rand.adapt.ibits] for more details on the constants calculated below.
   //
   // It is preferable to use roughly the same number of bits from each generator
@@ -199,21 +176,44 @@
   // `kSmallIters` and `kLargeIters` times respectively such
   // that
   //
-  //    `kTotalWidth == kSmallIters * kSmallWidth
-  //                    + kLargeIters * kLargeWidth`
+  //    `kResultBits == kSmallIters * kSmallBits
+  //                    + kLargeIters * kLargeBits`
   //
-  // where `kTotalWidth` is the total number of bits in `result_type`.
+  // where `kResultBits` is the total number of bits in `result_type`.
   //
-  constexpr size_t kTotalWidth = std::numeric_limits<result_type>::digits;
-  constexpr size_t kUrbgWidth = NumBits<URBG>();
-  constexpr size_t kTotalIters =
-      kTotalWidth / kUrbgWidth + (kTotalWidth % kUrbgWidth != 0);
-  constexpr size_t kSmallWidth = kTotalWidth / kTotalIters;
-  constexpr size_t kLargeWidth = kSmallWidth + 1;
+  static constexpr size_t kResultBits =
+      std::numeric_limits<result_type>::digits;                      // w
+  static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>();  // R
+  static constexpr size_t kUrbgBits = NumBits<URBG>();               // m
+
+  // compute the initial estimate of the bits used.
+  // [rand.adapt.ibits] 2 (c)
+  static constexpr size_t kA =  // ceil(w/m)
+      (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0);  // n'
+
+  static constexpr size_t kABits = kResultBits / kA;  // w0'
+  static constexpr urbg_result_type kARejection =
+      ((kUrbgRange >> kABits) << kABits);  // y0'
+
+  // refine the selection to reduce the rejection frequency.
+  static constexpr size_t kTotalIters =
+      ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1);  // n
+
+  // [rand.adapt.ibits] 2 (b)
+  static constexpr size_t kSmallIters =
+      kTotalIters - (kResultBits % kTotalIters);                   // n0
+  static constexpr size_t kSmallBits = kResultBits / kTotalIters;  // w0
+  static constexpr urbg_result_type kSmallRejection =
+      ((kUrbgRange >> kSmallBits) << kSmallBits);  // y0
+
+  static constexpr size_t kLargeBits = kSmallBits + 1;  // w0+1
+  static constexpr urbg_result_type kLargeRejection =
+      ((kUrbgRange >> kLargeBits) << kLargeBits);  // y1
+
   //
-  // Because `kLargeWidth == kSmallWidth + 1`, it follows that
+  // Because `kLargeBits == kSmallBits + 1`, it follows that
   //
-  //     `kTotalWidth == kTotalIters * kSmallWidth + kLargeIters`
+  //     `kResultBits == kSmallIters * kSmallBits + kLargeIters`
   //
   // and therefore
   //
@@ -224,36 +224,40 @@
   // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then
   // there would be no need for any large iterations (i.e., one loop would
   // suffice), and indeed, in this case, `kLargeIters` would be zero.
-  constexpr size_t kLargeIters = kTotalWidth % kSmallWidth;
-  constexpr size_t kSmallIters =
-      (kTotalWidth - (kLargeWidth * kLargeIters)) / kSmallWidth;
+  static_assert(kResultBits == kSmallIters * kSmallBits +
+                                   (kTotalIters - kSmallIters) * kLargeBits,
+                "Error in looping constant calculations.");
 
-  static_assert(
-      kTotalWidth == kSmallIters * kSmallWidth + kLargeIters * kLargeWidth,
-      "Error in looping constant calculations.");
+  // The small shift is essentially small bits, but due to the potential
+  // of generating a smaller result_type from a larger urbg type, the actual
+  // shift might be 0.
+  static constexpr size_t kSmallShift = kSmallBits % kResultBits;
+  static constexpr auto kSmallMask =
+      MaskFromShift<urbg_result_type>(kSmallShift);
+  static constexpr size_t kLargeShift = kLargeBits % kResultBits;
+  static constexpr auto kLargeMask =
+      MaskFromShift<urbg_result_type>(kLargeShift);
+
+  static constexpr auto kMin = (URBG::min)();
 
   result_type s = 0;
-
-  constexpr size_t kSmallShift = kSmallWidth % kTotalWidth;
-  constexpr result_type kSmallMask = MaskFromShift(result_type{kSmallShift});
   for (size_t n = 0; n < kSmallIters; ++n) {
-    s = (s << kSmallShift) +
-        (static_cast<result_type>(PowerOfTwoVariate(g)) & kSmallMask);
+    urbg_result_type v;
+    do {
+      v = g() - kMin;
+    } while (v >= kSmallRejection);
+
+    s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask);
   }
 
-  constexpr size_t kLargeShift = kLargeWidth % kTotalWidth;
-  constexpr result_type kLargeMask = MaskFromShift(result_type{kLargeShift});
-  for (size_t n = 0; n < kLargeIters; ++n) {
-    s = (s << kLargeShift) +
-        (static_cast<result_type>(PowerOfTwoVariate(g)) & kLargeMask);
+  for (size_t n = kSmallIters; n < kTotalIters; ++n) {
+    urbg_result_type v;
+    do {
+      v = g() - kMin;
+    } while (v >= kLargeRejection);
+
+    s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask);
   }
-
-  static_assert(
-      kLargeShift == kSmallShift + 1 ||
-          (kLargeShift == 0 &&
-           kSmallShift == std::numeric_limits<result_type>::digits - 1),
-      "Error in looping constant calculations");
-
   return s;
 }
 
diff --git a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
index f5b837e..cee702df8 100644
--- a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
@@ -34,8 +34,8 @@
   using Limits = std::numeric_limits<TypeParam>;
   using FastBits = FastUniformBits<TypeParam>;
 
-  EXPECT_EQ(0, FastBits::min());
-  EXPECT_EQ(Limits::max(), FastBits::max());
+  EXPECT_EQ(0, (FastBits::min)());
+  EXPECT_EQ((Limits::max)(), (FastBits::max)());
 
   constexpr int kIters = 10000;
   std::random_device rd;
@@ -43,8 +43,8 @@
   FastBits fast;
   for (int i = 0; i < kIters; i++) {
     const auto v = fast(gen);
-    EXPECT_LE(v, FastBits::max());
-    EXPECT_GE(v, FastBits::min());
+    EXPECT_LE(v, (FastBits::max)());
+    EXPECT_GE(v, (FastBits::min)());
   }
 }
 
@@ -52,21 +52,26 @@
 struct FakeUrbg {
   using result_type = UIntType;
 
+  FakeUrbg() = default;
+  explicit FakeUrbg(bool r) : reject(r) {}
+
   static constexpr result_type(max)() { return Hi; }
   static constexpr result_type(min)() { return Lo; }
-  result_type operator()() { return Val; }
-};
+  result_type operator()() {
+    // when reject is set, return Hi half the time.
+    return ((++calls % 2) == 1 && reject) ? Hi : Val;
+  }
 
-using UrngOddbits = FakeUrbg<uint8_t, 1, 0xfe, 0x73>;
-using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;
-using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>;
-using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;
+  bool reject = false;
+  size_t calls = 0;
+};
 
 TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) {
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{0}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{1}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{2}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{3}));
+  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{4}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{16}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{17}));
   EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint8_t>::max)()));
@@ -75,6 +80,7 @@
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{1}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{2}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{3}));
+  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{4}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{16}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{17}));
   EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint16_t>::max)()));
@@ -91,181 +97,237 @@
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{1}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{2}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{3}));
+  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{4}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{64}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{17}));
   EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint64_t>::max)()));
 }
 
 TEST(FastUniformBitsTest, IntegerLog2) {
-  EXPECT_EQ(IntegerLog2(uint16_t{0}), 0);
-  EXPECT_EQ(IntegerLog2(uint16_t{1}), 0);
-  EXPECT_EQ(IntegerLog2(uint16_t{2}), 1);
-  EXPECT_EQ(IntegerLog2(uint16_t{3}), 1);
-  EXPECT_EQ(IntegerLog2(uint16_t{4}), 2);
-  EXPECT_EQ(IntegerLog2(uint16_t{5}), 2);
-  EXPECT_EQ(IntegerLog2(std::numeric_limits<uint64_t>::max()), 63);
+  EXPECT_EQ(0, IntegerLog2(uint16_t{0}));
+  EXPECT_EQ(0, IntegerLog2(uint16_t{1}));
+  EXPECT_EQ(1, IntegerLog2(uint16_t{2}));
+  EXPECT_EQ(1, IntegerLog2(uint16_t{3}));
+  EXPECT_EQ(2, IntegerLog2(uint16_t{4}));
+  EXPECT_EQ(2, IntegerLog2(uint16_t{5}));
+  EXPECT_EQ(2, IntegerLog2(uint16_t{7}));
+  EXPECT_EQ(3, IntegerLog2(uint16_t{8}));
+  EXPECT_EQ(63, IntegerLog2((std::numeric_limits<uint64_t>::max)()));
 }
 
 TEST(FastUniformBitsTest, RangeSize) {
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 10>>()), 9);
+  EXPECT_EQ(2, (RangeSize<FakeUrbg<uint8_t, 0, 1>>()));
+  EXPECT_EQ(3, (RangeSize<FakeUrbg<uint8_t, 0, 2>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 0, 3>>()));
+  //  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint8_t, 2, 2>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint8_t, 2, 6>>()));
+  EXPECT_EQ(9, (RangeSize<FakeUrbg<uint8_t, 2, 10>>()));
   EXPECT_EQ(
-      (RangeSize<FakeUrbg<uint8_t, 0, std::numeric_limits<uint8_t>::max()>>()),
-      0);
+      0, (RangeSize<
+             FakeUrbg<uint8_t, 0, (std::numeric_limits<uint8_t>::max)()>>()));
 
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()), 18);
-  EXPECT_EQ((RangeSize<
-                FakeUrbg<uint16_t, 0, std::numeric_limits<uint16_t>::max()>>()),
-            0);
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 0, 3>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint16_t, 2, 6>>()));
+  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()));
+  EXPECT_EQ(
+      0, (RangeSize<
+             FakeUrbg<uint16_t, 0, (std::numeric_limits<uint16_t>::max)()>>()));
 
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()), 18);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()), 0);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()), 0xffffffff);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()), 0xfffffffe);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()), 0xfffffffd);
-  EXPECT_EQ((RangeSize<
-                FakeUrbg<uint32_t, 0, std::numeric_limits<uint32_t>::max()>>()),
-            0);
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 0, 3>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint32_t, 2, 6>>()));
+  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()));
+  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()));
+  EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()));
+  EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()));
+  EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()));
+  EXPECT_EQ(
+      0, (RangeSize<
+             FakeUrbg<uint32_t, 0, (std::numeric_limits<uint32_t>::max)()>>()));
 
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()), 18);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()), 0x100000000ull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()), 0xffffffffull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()), 0xfffffffeull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()), 0xfffffffdull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffffull>>()), 0ull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffffull>>()),
-            0xffffffffffffffffull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffeull>>()),
-            0xfffffffffffffffeull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffeull>>()),
-            0xfffffffffffffffdull);
-  EXPECT_EQ((RangeSize<
-                FakeUrbg<uint64_t, 0, std::numeric_limits<uint64_t>::max()>>()),
-            0);
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 0, 3>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint64_t, 2, 6>>()));
+  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()));
+  EXPECT_EQ(0x100000000, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()));
+  EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()));
+  EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()));
+  EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()));
+  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffff>>()));
+  EXPECT_EQ(0xffffffffffffffff,
+            (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffff>>()));
+  EXPECT_EQ(0xfffffffffffffffe,
+            (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffe>>()));
+  EXPECT_EQ(0xfffffffffffffffd,
+            (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffe>>()));
+  EXPECT_EQ(
+      0, (RangeSize<
+             FakeUrbg<uint64_t, 0, (std::numeric_limits<uint64_t>::max)()>>()));
 }
 
-TEST(FastUniformBitsTest, PowerOfTwoSubRangeSize) {
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 10>>()), 8);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint8_t, 0, std::numeric_limits<uint8_t>::max()>>()),
-            0);
+// The constants need to be choosen so that an infinite rejection loop doesn't
+// happen...
+using Urng1_5bit = FakeUrbg<uint8_t, 0, 2, 0>;  // ~1.5 bits (range 3)
+using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;
+using Urng22bits = FakeUrbg<uint32_t, 0, 0x3fffff, 0x301020>;
+using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>;  // ~31.9 bits
+using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;
+using Urng33bits =
+    FakeUrbg<uint64_t, 1, 0x1ffffffff, 0x013301033>;  // ~32.9 bits
+using Urng63bits = FakeUrbg<uint64_t, 1, 0xfffffffffffffffe,
+                            0xfedcba9012345678>;  // ~63.9 bits
+using Urng64bits =
+    FakeUrbg<uint64_t, 0, 0xffffffffffffffff, 0x123456780fedcba9>;
 
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 1000, 1017>>()), 16);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint16_t, 0, std::numeric_limits<uint16_t>::max()>>()),
-            0);
-
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1000, 1017>>()), 16);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()), 0);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()),
-            0x80000000);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()),
-            0x80000000);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint32_t, 0, std::numeric_limits<uint32_t>::max()>>()),
-            0);
-
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1000, 1017>>()), 16);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()),
-            0x100000000ull);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()),
-            0x80000000ull);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()),
-            0x80000000ull);
-  EXPECT_EQ(
-      (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffffull>>()),
-      0);
-  EXPECT_EQ(
-      (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffffull>>()),
-      0x8000000000000000ull);
-  EXPECT_EQ(
-      (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffeull>>()),
-      0x8000000000000000ull);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint64_t, 0, std::numeric_limits<uint64_t>::max()>>()),
-            0);
-}
-
-TEST(FastUniformBitsTest, Urng4_VariousOutputs) {
+TEST(FastUniformBitsTest, OutputsUpTo32Bits) {
   // Tests that how values are composed; the single-bit deltas should be spread
   // across each invocation.
+  Urng1_5bit urng1_5;
   Urng4bits urng4;
+  Urng22bits urng22;
   Urng31bits urng31;
   Urng32bits urng32;
+  Urng33bits urng33;
+  Urng63bits urng63;
+  Urng64bits urng64;
 
   // 8-bit types
   {
     FastUniformBits<uint8_t> fast8;
+    EXPECT_EQ(0x0, fast8(urng1_5));
     EXPECT_EQ(0x11, fast8(urng4));
+    EXPECT_EQ(0x20, fast8(urng22));
     EXPECT_EQ(0x2, fast8(urng31));
     EXPECT_EQ(0x1, fast8(urng32));
+    EXPECT_EQ(0x32, fast8(urng33));
+    EXPECT_EQ(0x77, fast8(urng63));
+    EXPECT_EQ(0xa9, fast8(urng64));
   }
 
   // 16-bit types
   {
     FastUniformBits<uint16_t> fast16;
+    EXPECT_EQ(0x0, fast16(urng1_5));
     EXPECT_EQ(0x1111, fast16(urng4));
-    EXPECT_EQ(0xf02, fast16(urng31));
-    EXPECT_EQ(0xf01, fast16(urng32));
+    EXPECT_EQ(0x1020, fast16(urng22));
+    EXPECT_EQ(0x0f02, fast16(urng31));
+    EXPECT_EQ(0x0f01, fast16(urng32));
+    EXPECT_EQ(0x1032, fast16(urng33));
+    EXPECT_EQ(0x5677, fast16(urng63));
+    EXPECT_EQ(0xcba9, fast16(urng64));
   }
 
   // 32-bit types
   {
     FastUniformBits<uint32_t> fast32;
+    EXPECT_EQ(0x0, fast32(urng1_5));
     EXPECT_EQ(0x11111111, fast32(urng4));
+    EXPECT_EQ(0x08301020, fast32(urng22));
     EXPECT_EQ(0x0f020f02, fast32(urng31));
     EXPECT_EQ(0x74010f01, fast32(urng32));
+    EXPECT_EQ(0x13301032, fast32(urng33));
+    EXPECT_EQ(0x12345677, fast32(urng63));
+    EXPECT_EQ(0x0fedcba9, fast32(urng64));
+  }
+}
+
+TEST(FastUniformBitsTest, Outputs64Bits) {
+  // Tests that how values are composed; the single-bit deltas should be spread
+  // across each invocation.
+  FastUniformBits<uint64_t> fast64;
+
+  {
+    FakeUrbg<uint8_t, 0, 1, 0> urng0;
+    FakeUrbg<uint8_t, 0, 1, 1> urng1;
+    Urng4bits urng4;
+    Urng22bits urng22;
+    Urng31bits urng31;
+    Urng32bits urng32;
+    Urng33bits urng33;
+    Urng63bits urng63;
+    Urng64bits urng64;
+
+    // somewhat degenerate cases only create a single bit.
+    EXPECT_EQ(0x0, fast64(urng0));
+    EXPECT_EQ(64, urng0.calls);
+    EXPECT_EQ(0xffffffffffffffff, fast64(urng1));
+    EXPECT_EQ(64, urng1.calls);
+
+    // less degenerate cases.
+    EXPECT_EQ(0x1111111111111111, fast64(urng4));
+    EXPECT_EQ(16, urng4.calls);
+    EXPECT_EQ(0x01020c0408301020, fast64(urng22));
+    EXPECT_EQ(3, urng22.calls);
+    EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));
+    EXPECT_EQ(3, urng31.calls);
+    EXPECT_EQ(0x74010f0174010f01, fast64(urng32));
+    EXPECT_EQ(2, urng32.calls);
+    EXPECT_EQ(0x808194040cb01032, fast64(urng33));
+    EXPECT_EQ(3, urng33.calls);
+    EXPECT_EQ(0x1234567712345677, fast64(urng63));
+    EXPECT_EQ(2, urng63.calls);
+    EXPECT_EQ(0x123456780fedcba9, fast64(urng64));
+    EXPECT_EQ(1, urng64.calls);
   }
 
-  // 64-bit types
+  // The 1.5 bit case is somewhat interesting in that the algorithm refinement
+  // causes one extra small sample. Comments here reference the names used in
+  // [rand.adapt.ibits] that correspond to this case.
   {
-    FastUniformBits<uint64_t> fast64;
-    EXPECT_EQ(0x1111111111111111, fast64(urng4));
+    Urng1_5bit urng1_5;
+
+    // w = 64
+    // R = 3
+    // m = 1
+    // n' = 64
+    // w0' = 1
+    // y0' = 2
+    // n = (1 <= 0) > 64 : 65 = 65
+    // n0 = 65 - (64%65) = 1
+    // n1 = 64
+    // w0 = 0
+    // y0 = 3
+    // w1 = 1
+    // y1 = 2
+    EXPECT_EQ(0x0, fast64(urng1_5));
+    EXPECT_EQ(65, urng1_5.calls);
+  }
+
+  // Validate rejections for non-power-of-2 cases.
+  {
+    Urng1_5bit urng1_5(true);
+    Urng31bits urng31(true);
+    Urng33bits urng33(true);
+    Urng63bits urng63(true);
+
+    // For 1.5 bits, there would be 1+2*64, except the first
+    // value was accepted and shifted off the end.
+    EXPECT_EQ(0, fast64(urng1_5));
+    EXPECT_EQ(128, urng1_5.calls);
     EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));
-    EXPECT_EQ(0x74010f0174010f01, fast64(urng32));
+    EXPECT_EQ(6, urng31.calls);
+    EXPECT_EQ(0x808194040cb01032, fast64(urng33));
+    EXPECT_EQ(6, urng33.calls);
+    EXPECT_EQ(0x1234567712345677, fast64(urng63));
+    EXPECT_EQ(4, urng63.calls);
   }
 }
 
 TEST(FastUniformBitsTest, URBG32bitRegression) {
   // Validate with deterministic 32-bit std::minstd_rand
   // to ensure that operator() performs as expected.
+
+  EXPECT_EQ(2147483646, RangeSize<std::minstd_rand>());
+  EXPECT_EQ(30, IntegerLog2(RangeSize<std::minstd_rand>()));
+
   std::minstd_rand gen(1);
   FastUniformBits<uint64_t> fast64;
 
-  EXPECT_EQ(0x05e47095f847c122ull, fast64(gen));
-  EXPECT_EQ(0x8f82c1ba30b64d22ull, fast64(gen));
-  EXPECT_EQ(0x3b971a3558155039ull, fast64(gen));
+  EXPECT_EQ(0x05e47095f8791f45, fast64(gen));
+  EXPECT_EQ(0x028be17e3c07c122, fast64(gen));
+  EXPECT_EQ(0x55d2847c1626e8c2, fast64(gen));
 }
 
 }  // namespace
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
index 5ee5fbc..634ee78 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
@@ -1155,7 +1155,8 @@
         {__LINE__, StrPrint("%.12a", dx), "%.12a"},
     };
     if (native_traits.hex_float_uses_minimal_precision_when_not_specified) {
-      expect.push_back({__LINE__, StrPrint("%12a", dx), "%12a"});
+      Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"};
+      expect.push_back(ex);
     }
     for (const Expectation &e : expect) {
       SCOPED_TRACE(e.line);
diff --git a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
index 3f876b9..2cd5ae2 100644
--- a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
@@ -90,6 +90,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.cc b/third_party/abseil-cpp/absl/synchronization/mutex.cc
index c7968f06..aafeb674 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.cc
@@ -59,6 +59,7 @@
 
 using absl::base_internal::CurrentThreadIdentityIfPresent;
 using absl::base_internal::PerThreadSynch;
+using absl::base_internal::SchedulingGuard;
 using absl::base_internal::ThreadIdentity;
 using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;
 using absl::synchronization_internal::GraphCycles;
@@ -141,7 +142,9 @@
 namespace {
   enum DelayMode { AGGRESSIVE, GENTLE };
 };
-static int Delay(int32_t c, DelayMode mode) {
+
+namespace synchronization_internal {
+int MutexDelay(int32_t c, int mode) {
   // If this a uniprocessor, only yield/sleep.  Otherwise, if the mode is
   // aggressive then spin many times before yielding.  If the mode is
   // gentle then spin only a few times before yielding.  Aggressive spinning is
@@ -153,6 +156,7 @@
     // Spin.
     c++;
   } else {
+    SchedulingGuard::ScopedEnable enable_rescheduling;
     ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);
     if (c == limit) {
       // Yield once.
@@ -167,6 +171,7 @@
   }
   return c;
 }
+}  // namespace synchronization_internal
 
 // --------------------------Generic atomic ops
 // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to
@@ -1051,6 +1056,7 @@
 // Try to remove thread s from the list of waiters on this mutex.
 // Does nothing if s is not on the waiter list.
 void Mutex::TryRemove(PerThreadSynch *s) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   intptr_t v = mu_.load(std::memory_order_relaxed);
   // acquire spinlock & lock
   if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait &&
@@ -1115,7 +1121,7 @@
       this->TryRemove(s);
       int c = 0;
       while (s->next != nullptr) {
-        c = Delay(c, GENTLE);
+        c = synchronization_internal::MutexDelay(c, GENTLE);
         this->TryRemove(s);
       }
       if (kDebugMode) {
@@ -1894,6 +1900,7 @@
 }
 
 void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   int c = 0;
   intptr_t v = mu_.load(std::memory_order_relaxed);
   if ((v & kMuEvent) != 0) {
@@ -1995,7 +2002,8 @@
     ABSL_RAW_CHECK(
         waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
         "detected illegal recursion into Mutex code");
-    c = Delay(c, GENTLE);          // delay, then try again
+    // delay, then try again
+    c = synchronization_internal::MutexDelay(c, GENTLE);
   }
   ABSL_RAW_CHECK(
       waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
@@ -2013,6 +2021,7 @@
 // or it is in the process of blocking on a condition variable; it must requeue
 // itself on the mutex/condvar to wait for its condition to become true.
 ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   intptr_t v = mu_.load(std::memory_order_relaxed);
   this->AssertReaderHeld();
   CheckForMutexCorruption(v, "Unlock");
@@ -2289,7 +2298,8 @@
       mu_.store(nv, std::memory_order_release);
       break;  // out of for(;;)-loop
     }
-    c = Delay(c, AGGRESSIVE);  // aggressive here; no one can proceed till we do
+    // aggressive here; no one can proceed till we do
+    c = synchronization_internal::MutexDelay(c, AGGRESSIVE);
   }                            // end of for(;;)-loop
 
   if (wake_list != kPerThreadSynchNull) {
@@ -2328,6 +2338,7 @@
 // It will later acquire the mutex with high probability.  Otherwise, we
 // enqueue thread w on this mutex.
 void Mutex::Fer(PerThreadSynch *w) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   int c = 0;
   ABSL_RAW_CHECK(w->waitp->cond == nullptr,
                  "Mutex::Fer while waiting on Condition");
@@ -2377,7 +2388,7 @@
         return;
       }
     }
-    c = Delay(c, GENTLE);
+    c = synchronization_internal::MutexDelay(c, GENTLE);
   }
 }
 
@@ -2426,6 +2437,7 @@
 
 // Remove thread s from the list of waiters on this condition variable.
 void CondVar::Remove(PerThreadSynch *s) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   intptr_t v;
   int c = 0;
   for (v = cv_.load(std::memory_order_relaxed);;
@@ -2454,7 +2466,8 @@
                 std::memory_order_release);
       return;
     } else {
-      c = Delay(c, GENTLE);            // try again after a delay
+      // try again after a delay
+      c = synchronization_internal::MutexDelay(c, GENTLE);
     }
   }
 }
@@ -2487,7 +2500,7 @@
          !cv_word->compare_exchange_weak(v, v | kCvSpin,
                                          std::memory_order_acquire,
                                          std::memory_order_relaxed)) {
-    c = Delay(c, GENTLE);
+    c = synchronization_internal::MutexDelay(c, GENTLE);
     v = cv_word->load(std::memory_order_relaxed);
   }
   ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be");
@@ -2586,6 +2599,7 @@
 }
 
 void CondVar::Signal() {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
   intptr_t v;
   int c = 0;
@@ -2618,7 +2632,7 @@
       ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
       return;
     } else {
-      c = Delay(c, GENTLE);
+      c = synchronization_internal::MutexDelay(c, GENTLE);
     }
   }
   ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
@@ -2655,7 +2669,8 @@
       ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
       return;
     } else {
-      c = Delay(c, GENTLE);           // try again after a delay
+      // try again after a delay
+      c = synchronization_internal::MutexDelay(c, GENTLE);
     }
   }
   ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.h b/third_party/abseil-cpp/absl/synchronization/mutex.h
index 876698c..52401fe 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex.h
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.h
@@ -685,6 +685,11 @@
   //     return processed_ >= current;
   //   };
   //   mu_.Await(Condition(&reached));
+  //
+  // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReadHeld()" in the
+  // lambda as it may be called when the mutex is being unlocked from a scope
+  // holding only a reader lock, which will make the assertion not fulfilled and
+  // crash the binary.
 
   // See class comment for performance advice. In particular, if there
   // might be more than one waiter for the same condition, make sure
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
index 2e02233..d8cb047 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
@@ -654,14 +654,23 @@
 }
 
 // Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday,
-// and the day on which weeks are defined to start.
-void FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
+// and the day on which weeks are defined to start.  Returns false if year
+// would need to move outside its bounds.
+bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
   const civil_year y(*year % 400);
   civil_day cd = prev_weekday(y, week_start);  // week 0
   cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7);
-  *year += cd.year() - y.year();
+  if (const year_t shift = cd.year() - y.year()) {
+    if (shift > 0) {
+      if (*year > std::numeric_limits<year_t>::max() - shift) return false;
+    } else {
+      if (*year < std::numeric_limits<year_t>::min() - shift) return false;
+    }
+    *year += shift;
+  }
   tm->tm_mon = cd.month() - 1;
   tm->tm_mday = cd.day();
+  return true;
 }
 
 }  // namespace
@@ -965,7 +974,12 @@
   }
 
   // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number.
-  if (week_num != -1) FromWeek(week_num, week_start, &year, &tm);
+  if (week_num != -1) {
+    if (!FromWeek(week_num, week_start, &year, &tm)) {
+      if (err != nullptr) *err = "Out-of-range field";
+      return false;
+    }
+  }
 
   const int month = tm.tm_mon + 1;
   civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
index e625a839f..a11f93e2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -1481,6 +1481,11 @@
   EXPECT_EQ(exp, tp);
   EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp));
   EXPECT_EQ(exp, tp);
+
+  // Slipping into the previous/following calendar years should fail when
+  // we're already at the extremes.
+  EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp));
+  EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp));
 }
 
 TEST(Parse, MaxRange) {
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
index 665fb42..7ccda11 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
@@ -40,7 +40,6 @@
 #include <cstdlib>
 #include <cstring>
 #include <functional>
-#include <iostream>
 #include <memory>
 #include <sstream>
 #include <string>
@@ -83,6 +82,27 @@
     366 * kSecsPerDay,
 };
 
+// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat).
+inline int ToPosixWeekday(weekday wd) {
+  switch (wd) {
+    case weekday::sunday:
+      return 0;
+    case weekday::monday:
+      return 1;
+    case weekday::tuesday:
+      return 2;
+    case weekday::wednesday:
+      return 3;
+    case weekday::thursday:
+      return 4;
+    case weekday::friday:
+      return 5;
+    case weekday::saturday:
+      return 6;
+  }
+  return 0; /*NOTREACHED*/
+}
+
 // Single-byte, unsigned numeric values are encoded directly.
 inline std::uint_fast8_t Decode8(const char* cp) {
   return static_cast<std::uint_fast8_t>(*cp) & 0xff;
@@ -188,15 +208,13 @@
   tt.is_dst = false;
   tt.abbr_index = 0;
 
-  // We temporarily add some redundant, contemporary (2013 through 2023)
+  // We temporarily add some redundant, contemporary (2015 through 2025)
   // transitions for performance reasons.  See TimeZoneInfo::LocalTime().
   // TODO: Fix the performance issue and remove the extra transitions.
   transitions_.clear();
   transitions_.reserve(12);
   for (const std::int_fast64_t unix_time : {
-           -(1LL << 59),  // BIG_BANG
-           1356998400LL,  // 2013-01-01T00:00:00+00:00
-           1388534400LL,  // 2014-01-01T00:00:00+00:00
+           -(1LL << 59),  // a "first half" transition
            1420070400LL,  // 2015-01-01T00:00:00+00:00
            1451606400LL,  // 2016-01-01T00:00:00+00:00
            1483228800LL,  // 2017-01-01T00:00:00+00:00
@@ -206,7 +224,8 @@
            1609459200LL,  // 2021-01-01T00:00:00+00:00
            1640995200LL,  // 2022-01-01T00:00:00+00:00
            1672531200LL,  // 2023-01-01T00:00:00+00:00
-           2147483647LL,  // 2^31 - 1
+           1704067200LL,  // 2024-01-01T00:00:00+00:00
+           1735689600LL,  // 2025-01-01T00:00:00+00:00
        }) {
     Transition& tr(*transitions_.emplace(transitions_.end()));
     tr.unix_time = unix_time;
@@ -217,8 +236,8 @@
 
   default_transition_type_ = 0;
   abbreviations_ = FixedOffsetToAbbr(offset);
-  abbreviations_.append(1, '\0');  // add NUL
-  future_spec_.clear();            // never needed for a fixed-offset zone
+  abbreviations_.append(1, '\0');
+  future_spec_.clear();  // never needed for a fixed-offset zone
   extended_ = false;
 
   tt.civil_max = LocalTime(seconds::max().count(), tt).cs;
@@ -259,21 +278,6 @@
   return len;
 }
 
-// Check that the TransitionType has the expected offset/is_dst/abbreviation.
-void TimeZoneInfo::CheckTransition(const std::string& name,
-                                   const TransitionType& tt,
-                                   std::int_fast32_t offset, bool is_dst,
-                                   const std::string& abbr) const {
-  if (tt.utc_offset != offset || tt.is_dst != is_dst ||
-      &abbreviations_[tt.abbr_index] != abbr) {
-    std::clog << name << ": Transition"
-              << " offset=" << tt.utc_offset << "/"
-              << (tt.is_dst ? "DST" : "STD")
-              << "/abbr=" << &abbreviations_[tt.abbr_index]
-              << " does not match POSIX spec '" << future_spec_ << "'\n";
-  }
-}
-
 // zic(8) can generate no-op transitions when a zone changes rules at an
 // instant when there is actually no discontinuity.  So we check whether
 // two transitions have equivalent types (same offset/is_dst/abbr).
@@ -282,117 +286,108 @@
   if (tt1_index == tt2_index) return true;
   const TransitionType& tt1(transition_types_[tt1_index]);
   const TransitionType& tt2(transition_types_[tt2_index]);
-  if (tt1.is_dst != tt2.is_dst) return false;
   if (tt1.utc_offset != tt2.utc_offset) return false;
+  if (tt1.is_dst != tt2.is_dst) return false;
   if (tt1.abbr_index != tt2.abbr_index) return false;
   return true;
 }
 
+// Find/make a transition type with these attributes.
+bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
+                                     const std::string& abbr,
+                                     std::uint_fast8_t* index) {
+  std::size_t type_index = 0;
+  std::size_t abbr_index = abbreviations_.size();
+  for (; type_index != transition_types_.size(); ++type_index) {
+    const TransitionType& tt(transition_types_[type_index]);
+    const char* tt_abbr = &abbreviations_[tt.abbr_index];
+    if (tt_abbr == abbr) abbr_index = tt.abbr_index;
+    if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) {
+      if (abbr_index == tt.abbr_index) break;  // reuse
+    }
+  }
+  if (type_index > 255 || abbr_index > 255) {
+    // No index space (8 bits) available for a new type or abbreviation.
+    return false;
+  }
+  if (type_index == transition_types_.size()) {
+    TransitionType& tt(*transition_types_.emplace(transition_types_.end()));
+    tt.utc_offset = static_cast<std::int_least32_t>(utc_offset);
+    tt.is_dst = is_dst;
+    if (abbr_index == abbreviations_.size()) {
+      abbreviations_.append(abbr);
+      abbreviations_.append(1, '\0');
+    }
+    tt.abbr_index = static_cast<std::uint_least8_t>(abbr_index);
+  }
+  *index = static_cast<std::uint_least8_t>(type_index);
+  return true;
+}
+
 // Use the POSIX-TZ-environment-variable-style string to handle times
 // in years after the last transition stored in the zoneinfo data.
-void TimeZoneInfo::ExtendTransitions(const std::string& name,
-                                     const Header& hdr) {
+bool TimeZoneInfo::ExtendTransitions() {
   extended_ = false;
-  bool extending = !future_spec_.empty();
+  if (future_spec_.empty()) return true;  // last transition prevails
 
   PosixTimeZone posix;
-  if (extending && !ParsePosixSpec(future_spec_, &posix)) {
-    std::clog << name << ": Failed to parse '" << future_spec_ << "'\n";
-    extending = false;
+  if (!ParsePosixSpec(future_spec_, &posix)) return false;
+
+  // Find transition type for the future std specification.
+  std::uint_fast8_t std_ti;
+  if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti))
+    return false;
+
+  if (posix.dst_abbr.empty()) {  // std only
+    // The future specification should match the last transition, and
+    // that means that handling the future will fall out naturally.
+    return EquivTransitions(transitions_.back().type_index, std_ti);
   }
 
-  if (extending && posix.dst_abbr.empty()) {  // std only
-    // The future specification should match the last/default transition,
-    // and that means that handling the future will fall out naturally.
-    std::uint_fast8_t index = default_transition_type_;
-    if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index;
-    const TransitionType& tt(transition_types_[index]);
-    CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr);
-    extending = false;
-  }
-
-  if (extending && hdr.timecnt < 2) {
-    std::clog << name << ": Too few transitions for POSIX spec\n";
-    extending = false;
-  }
-
-  if (!extending) {
-    // Ensure that there is always a transition in the second half of the
-    // time line (the BIG_BANG transition is in the first half) so that the
-    // signed difference between a civil_second and the civil_second of its
-    // previous transition is always representable, without overflow.
-    const Transition& last(transitions_.back());
-    if (last.unix_time < 0) {
-      const std::uint_fast8_t type_index = last.type_index;
-      Transition& tr(*transitions_.emplace(transitions_.end()));
-      tr.unix_time = 2147483647;  // 2038-01-19T03:14:07+00:00
-      tr.type_index = type_index;
-    }
-    return;  // last transition wins
-  }
+  // Find transition type for the future dst specification.
+  std::uint_fast8_t dst_ti;
+  if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti))
+    return false;
 
   // Extend the transitions for an additional 400 years using the
   // future specification. Years beyond those can be handled by
   // mapping back to a cycle-equivalent year within that range.
-  // zic(8) should probably do this so that we don't have to.
-  // TODO: Reduce the extension by the number of compatible
-  // transitions already in place.
-  transitions_.reserve(hdr.timecnt + 400 * 2 + 1);
-  transitions_.resize(hdr.timecnt + 400 * 2);
+  // We may need two additional transitions for the current year.
+  transitions_.reserve(transitions_.size() + 400 * 2 + 2);
   extended_ = true;
 
-  // The future specification should match the last two transitions,
-  // and those transitions should have different is_dst flags.  Note
-  // that nothing says the UTC offset used by the is_dst transition
-  // must be greater than that used by the !is_dst transition.  (See
-  // Europe/Dublin, for example.)
-  const Transition* tr0 = &transitions_[hdr.timecnt - 1];
-  const Transition* tr1 = &transitions_[hdr.timecnt - 2];
-  const TransitionType* tt0 = &transition_types_[tr0->type_index];
-  const TransitionType* tt1 = &transition_types_[tr1->type_index];
-  const TransitionType& dst(tt0->is_dst ? *tt0 : *tt1);
-  const TransitionType& std(tt0->is_dst ? *tt1 : *tt0);
-  CheckTransition(name, dst, posix.dst_offset, true, posix.dst_abbr);
-  CheckTransition(name, std, posix.std_offset, false, posix.std_abbr);
-
-  // Add the transitions to tr1 and back to tr0 for each extra year.
-  last_year_ = LocalTime(tr0->unix_time, *tt0).cs.year();
+  const Transition& last(transitions_.back());
+  const std::int_fast64_t last_time = last.unix_time;
+  const TransitionType& last_tt(transition_types_[last.type_index]);
+  last_year_ = LocalTime(last_time, last_tt).cs.year();
   bool leap_year = IsLeap(last_year_);
-  const civil_day jan1(last_year_, 1, 1);
-  std::int_fast64_t jan1_time = civil_second(jan1) - civil_second();
-  int jan1_weekday = (static_cast<int>(get_weekday(jan1)) + 1) % 7;
-  Transition* tr = &transitions_[hdr.timecnt];  // next trans to fill
-  if (LocalTime(tr1->unix_time, *tt1).cs.year() != last_year_) {
-    // Add a single extra transition to align to a calendar year.
-    transitions_.resize(transitions_.size() + 1);
-    assert(tr == &transitions_[hdr.timecnt]);  // no reallocation
-    const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
-    std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
-    tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
-    tr++->type_index = tr1->type_index;
-    tr0 = &transitions_[hdr.timecnt];
-    tr1 = &transitions_[hdr.timecnt - 1];
-    tt0 = &transition_types_[tr0->type_index];
-    tt1 = &transition_types_[tr1->type_index];
-  }
-  const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
-  const PosixTransition& pt0(tt0->is_dst ? posix.dst_start : posix.dst_end);
-  for (const year_t limit = last_year_ + 400; last_year_ < limit;) {
-    last_year_ += 1;  // an additional year of generated transitions
+  const civil_second jan1(last_year_);
+  std::int_fast64_t jan1_time = jan1 - civil_second();
+  int jan1_weekday = ToPosixWeekday(get_weekday(jan1));
+
+  Transition dst = {0, dst_ti, civil_second(), civil_second()};
+  Transition std = {0, std_ti, civil_second(), civil_second()};
+  for (const year_t limit = last_year_ + 400;; ++last_year_) {
+    auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start);
+    auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end);
+    dst.unix_time = jan1_time + dst_trans_off - posix.std_offset;
+    std.unix_time = jan1_time + std_trans_off - posix.dst_offset;
+    const auto* ta = dst.unix_time < std.unix_time ? &dst : &std;
+    const auto* tb = dst.unix_time < std.unix_time ? &std : &dst;
+    if (last_time < tb->unix_time) {
+      if (last_time < ta->unix_time) transitions_.push_back(*ta);
+      transitions_.push_back(*tb);
+    }
+    if (last_year_ == limit) break;
     jan1_time += kSecsPerYear[leap_year];
     jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;
-    leap_year = !leap_year && IsLeap(last_year_);
-    std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
-    tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
-    tr++->type_index = tr1->type_index;
-    std::int_fast64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0);
-    tr->unix_time = jan1_time + tr0_offset - tt1->utc_offset;
-    tr++->type_index = tr0->type_index;
+    leap_year = !leap_year && IsLeap(last_year_ + 1);
   }
-  assert(tr == &transitions_[0] + transitions_.size());
+
+  return true;
 }
 
-bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
+bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
   // Read and validate the header.
   tzhead tzh;
   if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
@@ -430,7 +425,7 @@
   const char* bp = tbuf.data();
 
   // Decode and validate the transitions.
-  transitions_.reserve(hdr.timecnt + 2);  // We might add a couple.
+  transitions_.reserve(hdr.timecnt + 2);
   transitions_.resize(hdr.timecnt);
   for (std::size_t i = 0; i != hdr.timecnt; ++i) {
     transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp);
@@ -449,6 +444,7 @@
   }
 
   // Decode and validate the transition types.
+  transition_types_.reserve(hdr.typecnt + 2);
   transition_types_.resize(hdr.typecnt);
   for (std::size_t i = 0; i != hdr.typecnt; ++i) {
     transition_types_[i].utc_offset =
@@ -475,6 +471,7 @@
   }
 
   // Copy all the abbreviations.
+  abbreviations_.reserve(hdr.charcnt + 10);
   abbreviations_.assign(bp, hdr.charcnt);
   bp += hdr.charcnt;
 
@@ -525,19 +522,29 @@
   transitions_.resize(hdr.timecnt);
 
   // Ensure that there is always a transition in the first half of the
-  // time line (the second half is handled in ExtendTransitions()) so that
-  // the signed difference between a civil_second and the civil_second of
-  // its previous transition is always representable, without overflow.
-  // A contemporary zic will usually have already done this for us.
+  // time line (the second half is handled below) so that the signed
+  // difference between a civil_second and the civil_second of its
+  // previous transition is always representable, without overflow.
   if (transitions_.empty() || transitions_.front().unix_time >= 0) {
     Transition& tr(*transitions_.emplace(transitions_.begin()));
-    tr.unix_time = -(1LL << 59);  // see tz/zic.c "BIG_BANG"
+    tr.unix_time = -(1LL << 59);  // -18267312070-10-26T17:01:52+00:00
     tr.type_index = default_transition_type_;
-    hdr.timecnt += 1;
   }
 
   // Extend the transitions using the future specification.
-  ExtendTransitions(name, hdr);
+  if (!ExtendTransitions()) return false;
+
+  // Ensure that there is always a transition in the second half of the
+  // time line (the first half is handled above) so that the signed
+  // difference between a civil_second and the civil_second of its
+  // previous transition is always representable, without overflow.
+  const Transition& last(transitions_.back());
+  if (last.unix_time < 0) {
+    const std::uint_fast8_t type_index = last.type_index;
+    Transition& tr(*transitions_.emplace(transitions_.end()));
+    tr.unix_time = 2147483647;  // 2038-01-19T03:14:07+00:00
+    tr.type_index = type_index;
+  }
 
   // Compute the local civil time for each transition and the preceding
   // second. These will be used for reverse conversions in MakeTime().
@@ -723,7 +730,7 @@
         if (auto zip = AndroidZoneInfoSource::Open(name)) return zip;
         return nullptr;
       });
-  return zip != nullptr && Load(name, zip.get());
+  return zip != nullptr && Load(zip.get());
 }
 
 // BreakTime() translation for a particular transition type.
@@ -897,8 +904,8 @@
   const Transition* begin = &transitions_[0];
   const Transition* end = begin + transitions_.size();
   if (begin->unix_time <= -(1LL << 59)) {
-    // Do not report the BIG_BANG found in recent zoneinfo data as it is
-    // really a sentinel, not a transition.  See tz/zic.c.
+    // Do not report the BIG_BANG found in some zoneinfo data as it is
+    // really a sentinel, not a transition.  See pre-2018f tz/zic.c.
     ++begin;
   }
   std::int_fast64_t unix_time = ToUnixSeconds(tp);
@@ -923,8 +930,8 @@
   const Transition* begin = &transitions_[0];
   const Transition* end = begin + transitions_.size();
   if (begin->unix_time <= -(1LL << 59)) {
-    // Do not report the BIG_BANG found in recent zoneinfo data as it is
-    // really a sentinel, not a transition.  See tz/zic.c.
+    // Do not report the BIG_BANG found in some zoneinfo data as it is
+    // really a sentinel, not a transition.  See pre-2018f tz/zic.c.
     ++begin;
   }
   std::int_fast64_t unix_time = ToUnixSeconds(tp);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
index 2a10c06..068e34b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
@@ -95,15 +95,14 @@
     std::size_t DataLength(std::size_t time_len) const;
   };
 
-  void CheckTransition(const std::string& name, const TransitionType& tt,
-                       std::int_fast32_t offset, bool is_dst,
-                       const std::string& abbr) const;
+  bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
+                         const std::string& abbr, std::uint_fast8_t* index);
   bool EquivTransitions(std::uint_fast8_t tt1_index,
                         std::uint_fast8_t tt2_index) const;
-  void ExtendTransitions(const std::string& name, const Header& hdr);
+  bool ExtendTransitions();
 
   bool ResetToBuiltinUTC(const seconds& offset);
-  bool Load(const std::string& name, ZoneInfoSource* zip);
+  bool Load(ZoneInfoSource* zip);
 
   // Helpers for BreakTime() and MakeTime().
   time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
index 47cf84c..3fcc75b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -223,11 +223,10 @@
         civil_second() + ToUnixSeconds(time_point<seconds>::min());
     static const civil_second max_tp_cs =
         civil_second() + ToUnixSeconds(time_point<seconds>::max());
-    const time_point<seconds> tp =
-        (cs < min_tp_cs)
-            ? time_point<seconds>::min()
-            : (cs > max_tp_cs) ? time_point<seconds>::max()
-                               : FromUnixSeconds(cs - civil_second());
+    const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min()
+                                   : (cs > max_tp_cs)
+                                       ? time_point<seconds>::max()
+                                       : FromUnixSeconds(cs - civil_second());
     return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
   }
 
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h b/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
index 269fa36..659f84c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
@@ -108,15 +108,15 @@
 #ifndef TZ_MAX_TYPES
 /* This must be at least 17 for Europe/Samara and Europe/Vilnius.  */
 #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif                   /* !defined TZ_MAX_TYPES */
+#endif /* !defined TZ_MAX_TYPES */
 
 #ifndef TZ_MAX_CHARS
 #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
-                        /* (limited by what unsigned chars can hold) */
-#endif                  /* !defined TZ_MAX_CHARS */
+/* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
 
 #ifndef TZ_MAX_LEAPS
 #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-#endif                  /* !defined TZ_MAX_LEAPS */
+#endif /* !defined TZ_MAX_LEAPS */
 
 #endif /* !defined TZFILE_H */
diff --git a/third_party/abseil-cpp/absl/types/CMakeLists.txt b/third_party/abseil-cpp/absl/types/CMakeLists.txt
index 0dc0d2c..3f99ad8 100644
--- a/third_party/abseil-cpp/absl/types/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/types/CMakeLists.txt
@@ -259,7 +259,7 @@
     absl::strings
     absl::utility
     gmock_main
-  PUBLIC
+  TESTONLY
 )
 
 absl_cc_test(
diff --git a/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh b/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
index 0192ee49a..4e490676 100755
--- a/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -71,15 +71,16 @@
         -e CC="/opt/llvm/clang/bin/clang" \
         -e BAZEL_COMPILER="llvm" \
         -e BAZEL_CXXOPTS="-std=${std}" \
-        -e CPLUS_INCLUDE_PATH="/usr/include/c++/8" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
         /usr/local/bin/bazel test ... \
           --compilation_mode="${compilation_mode}" \
+          --copt="--gcc-toolchain=/usr/local" \
           --copt="${exceptions_mode}" \
           --copt=-Werror \
           --define="absl=1" \
           --keep_going \
+          --linkopt="--gcc-toolchain=/usr/local" \
           --show_timestamps \
           --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
           --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
diff --git a/third_party/abseil-cpp/ci/linux_docker_containers.sh b/third_party/abseil-cpp/ci/linux_docker_containers.sh
index b652071f4..483ce2a 100644
--- a/third_party/abseil-cpp/ci/linux_docker_containers.sh
+++ b/third_party/abseil-cpp/ci/linux_docker_containers.sh
@@ -16,6 +16,6 @@
 # Test scripts should source this file to get the identifiers.
 
 readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016"
-readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200706"
-readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200319"
+readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20200710"
+readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20200710"
 readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018"
diff --git a/third_party/abseil-cpp/symbols_arm64_dbg.def b/third_party/abseil-cpp/symbols_arm64_dbg.def
index 199802a..a67b0552 100644
--- a/third_party/abseil-cpp/symbols_arm64_dbg.def
+++ b/third_party/abseil-cpp/symbols_arm64_dbg.def
@@ -28,6 +28,7 @@
     ??$?0$$TX@?$__compressed_pair_elem@PEAUViableSubstitution@strings_internal@absl@@$0A@$0A@@__1@std@@QEAA@$$QEA$$T@Z
     ??$?0$$TX@?$__compressed_pair_elem@PEAVFormatArgImpl@str_format_internal@absl@@$0A@$0A@@__1@std@@QEAA@$$QEA$$T@Z
     ??$?0$$V@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@@Z
+    ??$?0$$V@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$?0$00X@?$__compressed_pair@U?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@23@@__1@std@@QEAA@XZ
     ??$?0$00X@?$unique_ptr@$$BY0A@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QEAA@XZ
     ??$?0$00X@?$unique_ptr@$$CBVImpl@time_zone@cctz@time_internal@absl@@U?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@PEBVImpl@time_zone@cctz@time_internal@absl@@@Z
@@ -99,6 +100,7 @@
     ??$?0PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@$00@?$__compressed_pair@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QEAA@$$QEAPEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@@Z
     ??$?0PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@X@?$__compressed_pair_elem@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@$0A@$0A@@__1@std@@QEAA@$$QEAPEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@@Z
     ??$?0PEAUTransition@cctz@time_internal@absl@@@?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@__1@std@@QEAA@AEBV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@PEAX@Z
+    ??$?0PEAUTransitionType@cctz@time_internal@absl@@@?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@__1@std@@QEAA@AEBV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@PEAX@Z
     ??$?0PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$00@?$__compressed_pair@PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAA@$$QEAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
     ??$?0PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@?$__compressed_pair@PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAA@$$QEAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$$QEAU?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@12@@Z
     ??$?0PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@X@?$__compressed_pair_elem@PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$0A@$0A@@__1@std@@QEAA@$$QEAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
@@ -172,7 +174,9 @@
     ??$?D_J@absl@@YA?AVDuration@0@_JV10@@Z
     ??$?GPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV01234@@__1@std@@YA_JAEBV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@01@0@Z
     ??$?GPEAUTransition@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z
+    ??$?GPEAUTransitionType@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z
     ??$?GPEBUTransition@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@01@AEBV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@01@@Z
+    ??$?GPEBUTransitionType@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@01@AEBV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@01@@Z
     ??$?K_J@absl@@YA?AVDuration@0@V10@_J@Z
     ??$?MUsecond_tag@detail@cctz@time_internal@absl@@U01234@@detail@cctz@time_internal@absl@@YA_NAEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z
     ??$?NUsecond_tag@detail@cctz@time_internal@absl@@U01234@@detail@cctz@time_internal@absl@@YA_NAEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z
@@ -378,23 +382,29 @@
     ??$__construct@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@PEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__construct@UConversionItem@ParsedFormatBase@str_format_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QEAU5678@@Z
     ??$__construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@@Z
+    ??$__construct@UTransition@cctz@time_internal@absl@@AEBU1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@AEBU5678@@Z
     ??$__construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@$$QEAU5678@@Z
     ??$__construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@@Z
+    ??$__construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@$$QEAU5678@@Z
     ??$__construct@UViableSubstitution@strings_internal@absl@@AEAVstring_view@3@AEBV43@AEA_K@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PEAUViableSubstitution@strings_internal@absl@@AEAVstring_view@7@AEBV87@AEA_K@Z
     ??$__construct_at_end@PEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXPEBQEAUCordRep@cord_internal@absl@@0_K@Z
     ??$__construct_at_end@PEBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAXPEBVFormatArgImpl@str_format_internal@absl@@0_K@Z
     ??$__construct_at_end@V?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@12@0@Z
     ??$__construct_at_end@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@12@0@Z
+    ??$__construct_at_end@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@0@Z
     ??$__construct_backward_with_exception_guarantees@PEAUCordRep@cord_internal@absl@@@?$allocator_traits@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@PEAUCordRep@cord_internal@absl@@@12@PEAPEAUCordRep@cord_internal@absl@@1AEAPEAPEAU456@@Z
     ??$__construct_backward_with_exception_guarantees@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UTransition@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UTransitionType@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UViableSubstitution@strings_internal@absl@@@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PEAUViableSubstitution@strings_internal@absl@@1AEAPEAU456@@Z
     ??$__construct_forward_with_exception_guarantees@UTransition@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@1AEAPEAU4567@@Z
+    ??$__construct_forward_with_exception_guarantees@UTransitionType@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_node_hash@AEBUpiecewise_construct_t@__1@std@@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AEAA?AV?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@12@_KAEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__construct_one_at_end@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
+    ??$__construct_one_at_end@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
     ??$__construct_one_at_end@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$__construct_one_at_end@AEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
+    ??$__construct_one_at_end@AEBUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ??$__construct_one_at_end@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__construct_range_forward@$$CBVFormatArgImpl@str_format_internal@absl@@V123@V123@V123@@?$allocator_traits@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@VFormatArgImpl@str_format_internal@absl@@@12@PEBVFormatArgImpl@str_format_internal@absl@@1AEAPEAV456@@Z
     ??$__construct_range_forward@QEAUCordRep@cord_internal@absl@@PEAU123@PEAU123@PEAU123@@?$allocator_traits@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@PEAUCordRep@cord_internal@absl@@@12@PEBQEAUCordRep@cord_internal@absl@@1AEAPEAPEAU456@@Z
@@ -420,14 +430,18 @@
     ??$__distance@PEBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YA_JPEBVFormatArgImpl@str_format_internal@absl@@0Urandom_access_iterator_tag@01@@Z
     ??$__distance@V?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
     ??$__distance@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
+    ??$__distance@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
     ??$__emplace_back_slow_path@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__lower_bound@AEAUByUnixTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByUnixTime@2345@@Z
     ??$__move@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$__move@UTransition@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$__move@UTransitionType@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$__move_backward@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$__move_backward@UTransition@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$__move_backward@UTransitionType@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$__push_back_slow_path@AEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
+    ??$__push_back_slow_path@AEBUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ??$__push_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__to_raw_pointer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z
     ??$__to_raw_pointer@PEAUCordRep@cord_internal@absl@@@__1@std@@YAPEAPEAUCordRep@cord_internal@absl@@PEAPEAU234@@Z
@@ -438,6 +452,7 @@
     ??$__to_raw_pointer@VFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPEAVFormatArgImpl@str_format_internal@absl@@PEAV234@@Z
     ??$__unwrap_iter@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z
     ??$__unwrap_iter@PEAUTransition@cctz@time_internal@absl@@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@@Z
+    ??$__unwrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@@Z
     ??$__unwrap_iter@PEAVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPEAVFormatArgImpl@str_format_internal@absl@@PEAV234@@Z
     ??$__unwrap_iter@PEBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPEBVFormatArgImpl@str_format_internal@absl@@PEBV234@@Z
     ??$__upper_bound@AEAUByCivilTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByCivilTime@2345@@Z
@@ -489,10 +504,14 @@
     ??$construct@USubRange@absl@@U12@@?$allocator_traits@V?$allocator@USubRange@absl@@@__1@std@@@absl@@SAXAEAV?$allocator@USubRange@absl@@@__1@std@@PEAUSubRange@1@$$QEAU51@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransition@cctz@time_internal@absl@@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@@Z
+    ??$construct@UTransition@cctz@time_internal@absl@@AEBU1234@@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransition@cctz@time_internal@absl@@AEBU3456@@Z
+    ??$construct@UTransition@cctz@time_internal@absl@@AEBU1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@AEBU4567@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransition@cctz@time_internal@absl@@$$QEAU3456@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@$$QEAU4567@@Z
     ??$construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransitionType@cctz@time_internal@absl@@@Z
     ??$construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@@Z
+    ??$construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransitionType@cctz@time_internal@absl@@$$QEAU3456@@Z
+    ??$construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@$$QEAU4567@@Z
     ??$construct@UViableSubstitution@strings_internal@absl@@AEAVstring_view@3@AEBV43@AEA_K@?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@QEAAXPEAUViableSubstitution@strings_internal@absl@@AEAVstring_view@5@AEBV65@AEA_K@Z
     ??$construct@UViableSubstitution@strings_internal@absl@@AEAVstring_view@3@AEBV43@AEA_K@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PEAUViableSubstitution@strings_internal@absl@@AEAVstring_view@6@AEBV76@AEA_K@Z
     ??$construct@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IEAAX$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
@@ -529,8 +548,11 @@
     ??$distance@PEBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YA_JPEBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$distance@V?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@01@0@Z
     ??$distance@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z
+    ??$distance@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
     ??$emplace_back@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$emplace_back@AEBH@?$InlinedVector@H$0CP@V?$allocator@H@__1@std@@@absl@@QEAAAEAHAEBH@Z
     ??$emplace_back@AEBQEAUCordRep@cord_internal@absl@@@?$InlinedVector@PEAUCordRep@cord_internal@absl@@$01V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QEAAAEAPEAUCordRep@cord_internal@1@AEBQEAU231@@Z
@@ -575,6 +597,7 @@
     ??$forward@AEBQEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAAEBQEBVImpl@time_zone@cctz@time_internal@absl@@AEBQEBV23456@@Z
     ??$forward@AEBUHashtablezInfo@container_internal@absl@@@__1@std@@YAAEBUHashtablezInfo@container_internal@absl@@AEBU234@@Z
     ??$forward@AEBUPayload@status_internal@absl@@@__1@std@@YAAEBUPayload@status_internal@absl@@AEBU234@@Z
+    ??$forward@AEBUTransition@cctz@time_internal@absl@@@__1@std@@YAAEBUTransition@cctz@time_internal@absl@@AEBU2345@@Z
     ??$forward@AEBV?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@YAAEBV?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@AEBV123@@Z
     ??$forward@AEBV?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@YAAEBV?$allocator@UPayload@status_internal@absl@@@__1@std@@AEBV123@@Z
     ??$forward@AEBVCord@absl@@@__1@std@@YAAEBVCord@absl@@AEBV23@@Z
@@ -596,6 +619,7 @@
     ??$forward@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@__1@std@@YA$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@01@@Z@AEAU2?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@34@QEAA@0@Z@@Z
     ??$forward@USubRange@absl@@@__1@std@@YA$$QEAUSubRange@absl@@AEAU23@@Z
     ??$forward@UTransition@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransition@cctz@time_internal@absl@@AEAU2345@@Z
+    ??$forward@UTransitionType@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransitionType@cctz@time_internal@absl@@AEAU2345@@Z
     ??$forward@V?$Span@I@absl@@@__1@std@@YA$$QEAV?$Span@I@absl@@AEAV23@@Z
     ??$forward@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@01@AEAV201@@Z
     ??$forward@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@01@AEAV201@@Z
@@ -656,6 +680,7 @@
     ??$move@AEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@__1@std@@YA$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@01@@Z@AEAU2?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@34@QEAA@0@Z@@Z
     ??$move@AEAUSubRange@absl@@@__1@std@@YA$$QEAUSubRange@absl@@AEAU23@@Z
     ??$move@AEAUTransition@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransition@cctz@time_internal@absl@@AEAU2345@@Z
+    ??$move@AEAUTransitionType@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransitionType@cctz@time_internal@absl@@AEAU2345@@Z
     ??$move@AEAUViableSubstitution@strings_internal@absl@@@__1@std@@YA$$QEAUViableSubstitution@strings_internal@absl@@AEAU234@@Z
     ??$move@AEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@01@AEAV201@@Z
     ??$move@AEAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@01@AEAV201@@Z
@@ -664,8 +689,10 @@
     ??$move@AEAVInlineRep@Cord@absl@@@__1@std@@YA$$QEAVInlineRep@Cord@absl@@AEAV234@@Z
     ??$move@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$move@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$move@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$move_backward@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$move_backward@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$move_backward@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$reset@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@?$unique_ptr@$$BY0A@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QEAAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@@Z
     ??$swap@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAXAEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z
     ??$swap@PEAPEAUCordRep@cord_internal@absl@@@__1@std@@YAXAEAPEAPEAUCordRep@cord_internal@absl@@0@Z
@@ -839,6 +866,7 @@
     ??0?$move_iterator@PEAUPayload@status_internal@absl@@@__1@std@@QEAA@PEAUPayload@status_internal@absl@@@Z
     ??0?$move_iterator@PEAUSubRange@absl@@@__1@std@@QEAA@PEAUSubRange@absl@@@Z
     ??0?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEAA@PEAUTransition@cctz@time_internal@absl@@@Z
+    ??0?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEAA@PEAUTransitionType@cctz@time_internal@absl@@@Z
     ??0?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@QEAA@XZ
     ??0?$optional@VCord@absl@@@absl@@QEAA@Unullopt_t@1@@Z
     ??0?$optional_data@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@optional_internal@absl@@IEAA@XZ
@@ -915,6 +943,8 @@
     ??0Refcount@cord_internal@absl@@QEAA@XZ
     ??0Rep@GraphCycles@synchronization_internal@absl@@QEAA@XZ
     ??0SchedulingHelper@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z
+    ??0ScopedDisable@SchedulingGuard@base_internal@absl@@QEAA@XZ
+    ??0ScopedEnable@SchedulingGuard@base_internal@absl@@QEAA@XZ
     ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z
     ??0SpinLockHolder@base_internal@absl@@QEAA@PEAVSpinLock@12@@Z
     ??0Status@absl@@QEAA@W4StatusCode@1@Vstring_view@1@@Z
@@ -1000,6 +1030,7 @@
     ??1?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
     ??1?$__split_buffer@UViableSubstitution@strings_internal@absl@@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
     ??1?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
+    ??1?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
     ??1?$__vector_base@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@IEAA@XZ
     ??1?$__vector_base@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@IEAA@XZ
     ??1?$__vector_base@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@IEAA@XZ
@@ -1048,6 +1079,8 @@
     ??1Refcount@cord_internal@absl@@QEAA@XZ
     ??1Rep@GraphCycles@synchronization_internal@absl@@QEAA@XZ
     ??1SchedulingHelper@base_internal@absl@@QEAA@XZ
+    ??1ScopedDisable@SchedulingGuard@base_internal@absl@@QEAA@XZ
+    ??1ScopedEnable@SchedulingGuard@base_internal@absl@@QEAA@XZ
     ??1SpinLockHolder@base_internal@absl@@QEAA@XZ
     ??1StatusRep@status_internal@absl@@QEAA@XZ
     ??1Storage@?$FixedArray@PEAUCordRep@cord_internal@absl@@$0?0V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QEAA@XZ
@@ -1174,6 +1207,7 @@
     ??D?$move_iterator@PEAUPayload@status_internal@absl@@@__1@std@@QEBA$$QEAUPayload@status_internal@absl@@XZ
     ??D?$move_iterator@PEAUSubRange@absl@@@__1@std@@QEBA$$QEAUSubRange@absl@@XZ
     ??D?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEBA$$QEAUTransition@cctz@time_internal@absl@@XZ
+    ??D?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBA$$QEAUTransitionType@cctz@time_internal@absl@@XZ
     ??D?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@QEGAAAEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@XZ
     ??D?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEBAAEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@XZ
     ??DChunkIterator@Cord@absl@@QEBA?AVstring_view@2@XZ
@@ -1188,6 +1222,7 @@
     ??E?$move_iterator@PEAUPayload@status_internal@absl@@@__1@std@@QEAAAEAV012@XZ
     ??E?$move_iterator@PEAUSubRange@absl@@@__1@std@@QEAAAEAV012@XZ
     ??E?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEAAAEAV012@XZ
+    ??E?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEAAAEAV012@XZ
     ??EChunkIterator@Cord@absl@@QEAAAEAV012@XZ
     ??Euint128@absl@@QEAAAEAV01@XZ
     ??Gabsl@@YA?AVDuration@0@V10@0@Z
@@ -1400,7 +1435,6 @@
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ
     ?CheckLengthInternal@string_view@absl@@CA_K_K@Z
     ?CheckNode@CordForest@absl@@CAXPEAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@AEBAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUTransitionType@234@H_N0@Z
     ?Chunks@Cord@absl@@QEBA?AVChunkRange@12@XZ
     ?CityHash32@hash_internal@absl@@YAIPEBD_K@Z
     ?CityHash64@hash_internal@absl@@YA_KPEBD_K@Z
@@ -1522,7 +1556,7 @@
     ?ErasePayload@Status@absl@@QEAA_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QEBA_NXZ
     ?Excess@str_format_internal@absl@@YA_K_K0@Z
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPEBDH@Z
@@ -1713,6 +1747,7 @@
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetTagForChar@str_format_internal@absl@@YA?AVConvTag@12@D@Z
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPEAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NH_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAE@Z
     ?GetWaiter@Waiter@synchronization_internal@absl@@SAPEAV123@PEAUThreadIdentity@base_internal@3@@Z
     ?GetWeekday@absl@@YA?AW4weekday@detail@cctz@time_internal@1@V?$civil_time@Usecond_tag@time_internal@absl@@@3451@@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QEBAIH@Z
@@ -1786,7 +1821,7 @@
     ?Load@?$AtomicHook@P6A?AV?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@Vstring_view@2@AEBVCord@2@@Z@base_internal@absl@@QEBAP6A?AV?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@3@Vstring_view@3@AEBVCord@3@@ZXZ
     ?Load@?$AtomicHook@P6A_NW4LogSeverity@absl@@PEBDHPEAPEADPEAH@Z@base_internal@absl@@QEBAP6A_NW4LogSeverity@3@PEBDHPEAPEADPEAH@ZXZ
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NPEAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z
@@ -1839,6 +1874,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QEAAXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AEAAXHPEBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AEAAXHPEBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?Name@Impl@time_zone@cctz@time_internal@absl@@QEBAAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@XZ
     ?Nanoseconds@absl@@YA?AVDuration@1@_J@Z
     ?NegateAndSubtractOne@time_internal@absl@@YA_J_J@Z
@@ -2206,6 +2242,7 @@
     ?ZeroDuration@absl@@YA?AVDuration@1@XZ
     ?__add_back_capacity@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
     ?__addr@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAPEAUTransition@cctz@time_internal@absl@@XZ
+    ?__addr@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAPEAUTransitionType@cctz@time_internal@absl@@XZ
     ?__alloc@?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@__1@std@@QEAAAEAV?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@XZ
     ?__alloc@?$__deque_base@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@IEAAAEAV?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ
     ?__alloc@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAAEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ
@@ -2404,6 +2441,7 @@
     ?__max_size@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@CA_KU?$integral_constant@_N$00@23@AEBV?$allocator@UViableSubstitution@strings_internal@absl@@@23@@Z
     ?__max_size@?$allocator_traits@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@CA_KU?$integral_constant@_N$00@23@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@23@@Z
     ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXPEAUTransition@cctz@time_internal@absl@@00@Z
+    ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXPEAUTransitionType@cctz@time_internal@absl@@00@Z
     ?__node_alloc@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAAEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@23@XZ
     ?__ptr@?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@QEAAPEAU123@XZ
     ?__recommend@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEBA_K_K@Z
@@ -2417,6 +2455,7 @@
     ?__swap_out_circular_buffer@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UConversionItem@ParsedFormatBase@str_format_internal@absl@@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransition@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransitionType@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UViableSubstitution@strings_internal@absl@@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@23@@Z
     ?__upcast@?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@QEAAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@XZ
@@ -2482,8 +2521,10 @@
     ?base@?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBAPEAUTransitionType@cctz@time_internal@absl@@XZ
     ?base@?$__wrap_iter@PEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@QEBAPEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ
     ?base@?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@__1@std@@QEBAPEBUTransition@cctz@time_internal@absl@@XZ
+    ?base@?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBAPEBUTransitionType@cctz@time_internal@absl@@XZ
     ?base@?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@QEBAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ
     ?base@?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEBAPEAUTransition@cctz@time_internal@absl@@XZ
+    ?base@?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBAPEAUTransitionType@cctz@time_internal@absl@@XZ
     ?begin@?$InlinedVector@PEAUCordRep@cord_internal@absl@@$0CP@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QEAAPEAPEAUCordRep@cord_internal@2@XZ
     ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ
     ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ
@@ -2747,6 +2788,7 @@
     ?get@?$Storage@_K$00$0A@@internal_compressed_tuple@container_internal@absl@@QEGBAAEB_KXZ
     ?get@?$Storage@_K$0A@$0A@@internal_compressed_tuple@container_internal@absl@@QEGBAAEB_KXZ
     ?get@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAAEAUTransition@cctz@time_internal@absl@@XZ
+    ?get@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAAEAUTransitionType@cctz@time_internal@absl@@XZ
     ?get@?$unique_ptr@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@QEBAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ
     ?get@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@__1@std@@QEBAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@XZ
     ?get@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEBAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@XZ
@@ -2875,6 +2917,7 @@
     ?push_back@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_back@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
     ?push_back@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
+    ?push_back@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?raw_code@Status@absl@@QEBAHXZ
@@ -2892,6 +2935,7 @@
     ?rend@string_view@absl@@QEBA?AV?$reverse_iterator@PEBD@__1@std@@XZ
     ?replace_tree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reset@?$unique_ptr@$$CBVImpl@time_zone@cctz@time_internal@absl@@U?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?reset@?$unique_ptr@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@QEAAXPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_arm64_rel.def b/third_party/abseil-cpp/symbols_arm64_rel.def
index 3c97702..98a8803 100644
--- a/third_party/abseil-cpp/symbols_arm64_rel.def
+++ b/third_party/abseil-cpp/symbols_arm64_rel.def
@@ -62,11 +62,14 @@
     ??$ToChronoDuration@V?$duration@JV?$ratio@$0OBA@$00@__1@std@@@chrono@__1@std@@@time_internal@absl@@YA?AV?$duration@JV?$ratio@$0OBA@$00@__1@std@@@chrono@__1@std@@VDuration@1@@Z
     ??$__emplace_back_slow_path@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
+    ??$__push_back_slow_path@AEBUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ??$__upper_bound@AEAUByCivilTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByCivilTime@2345@@Z
     ??$assign@PEBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@QEAAXPEBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$assign@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IEAAX$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
     ??$find@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@Vstring_view@2@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@XZ
@@ -226,7 +229,6 @@
     ?Ceil@absl@@YA?AVDuration@1@V21@0@Z
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ
     ?CheckNode@CordForest@absl@@CAXPEAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@AEBAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUTransitionType@234@H_N0@Z
     ?CityHash32@hash_internal@absl@@YAIPEBD_K@Z
     ?CityHash64@hash_internal@absl@@YA_KPEBD_K@Z
     ?CityHash64WithSeed@hash_internal@absl@@YA_KPEBD_K1@Z
@@ -297,7 +299,7 @@
     ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z
     ?ErasePayload@Status@absl@@QEAA_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QEBA_NXZ
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPEBDH@Z
@@ -381,6 +383,7 @@
     ?GetStride@ExponentialBiased@base_internal@absl@@QEAA_J_J@Z
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPEAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NH_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAE@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QEBAIH@Z
     ?GetWord@?$BigUnsigned@$0FE@@strings_internal@absl@@QEBAIH@Z
     ?Global@HashtablezSampler@container_internal@absl@@SAAEAV123@XZ
@@ -423,7 +426,7 @@
     ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@W4LengthMod@12@@Z
     ?LengthToTag@CordTestAccess@strings_internal@absl@@SAE_K@Z
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NPEAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z
@@ -456,6 +459,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QEAAXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AEAAXHPEBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AEAAXHPEBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPEAUArena@123@H@Z
     ?NewExternalWithUninitializedReleaser@cord_internal@absl@@YA?AUExternalRepReleaserPair@12@Vstring_view@2@P6A_KPEAX0@Z_K@Z
     ?NewRep@Status@absl@@CA_KW4StatusCode@2@Vstring_view@2@V?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@@Z
@@ -696,6 +700,7 @@
     ?__invoke@<lambda_1>@?0???$NewExternalRep@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@cord_internal@absl@@YAPEAUCordRep@23@Vstring_view@3@$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@3@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@Z@CA?A?<auto>@@PEAX0@Z
     ?__rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AEAAX_K@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransition@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransitionType@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__vallocate@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX_K@Z
     ?clear@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAXXZ
     ?code@Status@absl@@QEBA?AW4StatusCode@2@XZ
@@ -746,6 +751,7 @@
     ?raw_code@Status@absl@@QEBAHXZ
     ?rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reset@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@__1@std@@QEAAXPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@@Z
     ?reset@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAAXPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_x64_dbg.def b/third_party/abseil-cpp/symbols_x64_dbg.def
index 9bc69da..4ddceb67 100644
--- a/third_party/abseil-cpp/symbols_x64_dbg.def
+++ b/third_party/abseil-cpp/symbols_x64_dbg.def
@@ -28,6 +28,7 @@
     ??$?0$$TX@?$__compressed_pair_elem@PEAUViableSubstitution@strings_internal@absl@@$0A@$0A@@__1@std@@QEAA@$$QEA$$T@Z
     ??$?0$$TX@?$__compressed_pair_elem@PEAVFormatArgImpl@str_format_internal@absl@@$0A@$0A@@__1@std@@QEAA@$$QEA$$T@Z
     ??$?0$$V@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@@Z
+    ??$?0$$V@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$?0$00X@?$__compressed_pair@U?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@23@@__1@std@@QEAA@XZ
     ??$?0$00X@?$unique_ptr@$$BY0A@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QEAA@XZ
     ??$?0$00X@?$unique_ptr@$$CBVImpl@time_zone@cctz@time_internal@absl@@U?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@PEBVImpl@time_zone@cctz@time_internal@absl@@@Z
@@ -99,6 +100,7 @@
     ??$?0PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@$00@?$__compressed_pair@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QEAA@$$QEAPEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@@Z
     ??$?0PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@X@?$__compressed_pair_elem@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@$0A@$0A@@__1@std@@QEAA@$$QEAPEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@@Z
     ??$?0PEAUTransition@cctz@time_internal@absl@@@?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@__1@std@@QEAA@AEBV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@PEAX@Z
+    ??$?0PEAUTransitionType@cctz@time_internal@absl@@@?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@__1@std@@QEAA@AEBV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@PEAX@Z
     ??$?0PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$00@?$__compressed_pair@PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAA@$$QEAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
     ??$?0PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@?$__compressed_pair@PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAA@$$QEAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$$QEAU?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@12@@Z
     ??$?0PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@X@?$__compressed_pair_elem@PEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$0A@$0A@@__1@std@@QEAA@$$QEAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
@@ -172,7 +174,9 @@
     ??$?D_J@absl@@YA?AVDuration@0@_JV10@@Z
     ??$?GPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV01234@@__1@std@@YA_JAEBV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@01@0@Z
     ??$?GPEAUTransition@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z
+    ??$?GPEAUTransitionType@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z
     ??$?GPEBUTransition@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@01@AEBV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@01@@Z
+    ??$?GPEBUTransitionType@cctz@time_internal@absl@@PEAU0123@@__1@std@@YA_JAEBV?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@01@AEBV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@01@@Z
     ??$?K_J@absl@@YA?AVDuration@0@V10@_J@Z
     ??$?MUsecond_tag@detail@cctz@time_internal@absl@@U01234@@detail@cctz@time_internal@absl@@YA_NAEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z
     ??$?NUsecond_tag@detail@cctz@time_internal@absl@@U01234@@detail@cctz@time_internal@absl@@YA_NAEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z
@@ -378,23 +382,29 @@
     ??$__construct@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@PEAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__construct@UConversionItem@ParsedFormatBase@str_format_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QEAU5678@@Z
     ??$__construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@@Z
+    ??$__construct@UTransition@cctz@time_internal@absl@@AEBU1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@AEBU5678@@Z
     ??$__construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@$$QEAU5678@@Z
     ??$__construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@@Z
+    ??$__construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@$$QEAU5678@@Z
     ??$__construct@UViableSubstitution@strings_internal@absl@@AEAVstring_view@3@AEBV43@AEA_K@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PEAUViableSubstitution@strings_internal@absl@@AEAVstring_view@7@AEBV87@AEA_K@Z
     ??$__construct_at_end@PEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXPEBQEAUCordRep@cord_internal@absl@@0_K@Z
     ??$__construct_at_end@PEBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAXPEBVFormatArgImpl@str_format_internal@absl@@0_K@Z
     ??$__construct_at_end@V?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@12@0@Z
     ??$__construct_at_end@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@12@0@Z
+    ??$__construct_at_end@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@12@0@Z
     ??$__construct_backward_with_exception_guarantees@PEAUCordRep@cord_internal@absl@@@?$allocator_traits@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@PEAUCordRep@cord_internal@absl@@@12@PEAPEAUCordRep@cord_internal@absl@@1AEAPEAPEAU456@@Z
     ??$__construct_backward_with_exception_guarantees@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UTransition@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UTransitionType@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UViableSubstitution@strings_internal@absl@@@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PEAUViableSubstitution@strings_internal@absl@@1AEAPEAU456@@Z
     ??$__construct_forward_with_exception_guarantees@UTransition@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@1AEAPEAU4567@@Z
+    ??$__construct_forward_with_exception_guarantees@UTransitionType@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@1AEAPEAU4567@@Z
     ??$__construct_node_hash@AEBUpiecewise_construct_t@__1@std@@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AEAA?AV?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@12@_KAEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__construct_one_at_end@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
+    ??$__construct_one_at_end@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
     ??$__construct_one_at_end@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$__construct_one_at_end@AEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
+    ??$__construct_one_at_end@AEBUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ??$__construct_one_at_end@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__construct_range_forward@$$CBVFormatArgImpl@str_format_internal@absl@@V123@V123@V123@@?$allocator_traits@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@VFormatArgImpl@str_format_internal@absl@@@12@PEBVFormatArgImpl@str_format_internal@absl@@1AEAPEAV456@@Z
     ??$__construct_range_forward@QEAUCordRep@cord_internal@absl@@PEAU123@PEAU123@PEAU123@@?$allocator_traits@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@PEAUCordRep@cord_internal@absl@@@12@PEBQEAUCordRep@cord_internal@absl@@1AEAPEAPEAU456@@Z
@@ -420,14 +430,18 @@
     ??$__distance@PEBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YA_JPEBVFormatArgImpl@str_format_internal@absl@@0Urandom_access_iterator_tag@01@@Z
     ??$__distance@V?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
     ??$__distance@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
+    ??$__distance@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
     ??$__emplace_back_slow_path@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__lower_bound@AEAUByUnixTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByUnixTime@2345@@Z
     ??$__move@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$__move@UTransition@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$__move@UTransitionType@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$__move_backward@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$__move_backward@UTransition@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$__move_backward@UTransitionType@cctz@time_internal@absl@@U1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$__push_back_slow_path@AEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
+    ??$__push_back_slow_path@AEBUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ??$__push_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__to_raw_pointer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z
     ??$__to_raw_pointer@PEAUCordRep@cord_internal@absl@@@__1@std@@YAPEAPEAUCordRep@cord_internal@absl@@PEAPEAU234@@Z
@@ -438,6 +452,7 @@
     ??$__to_raw_pointer@VFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPEAVFormatArgImpl@str_format_internal@absl@@PEAV234@@Z
     ??$__unwrap_iter@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@@Z
     ??$__unwrap_iter@PEAUTransition@cctz@time_internal@absl@@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@@Z
+    ??$__unwrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@@Z
     ??$__unwrap_iter@PEAVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPEAVFormatArgImpl@str_format_internal@absl@@PEAV234@@Z
     ??$__unwrap_iter@PEBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPEBVFormatArgImpl@str_format_internal@absl@@PEBV234@@Z
     ??$__upper_bound@AEAUByCivilTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByCivilTime@2345@@Z
@@ -491,10 +506,14 @@
     ??$construct@USubRange@absl@@U12@@?$allocator_traits@V?$allocator@USubRange@absl@@@__1@std@@@absl@@SAXAEAV?$allocator@USubRange@absl@@@__1@std@@PEAUSubRange@1@$$QEAU51@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransition@cctz@time_internal@absl@@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@@Z
+    ??$construct@UTransition@cctz@time_internal@absl@@AEBU1234@@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransition@cctz@time_internal@absl@@AEBU3456@@Z
+    ??$construct@UTransition@cctz@time_internal@absl@@AEBU1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@AEBU4567@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransition@cctz@time_internal@absl@@$$QEAU3456@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PEAUTransition@cctz@time_internal@absl@@$$QEAU4567@@Z
     ??$construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransitionType@cctz@time_internal@absl@@@Z
     ??$construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@@Z
+    ??$construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@QEAAXPEAUTransitionType@cctz@time_internal@absl@@$$QEAU3456@@Z
+    ??$construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PEAUTransitionType@cctz@time_internal@absl@@$$QEAU4567@@Z
     ??$construct@UViableSubstitution@strings_internal@absl@@AEAVstring_view@3@AEBV43@AEA_K@?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@QEAAXPEAUViableSubstitution@strings_internal@absl@@AEAVstring_view@5@AEBV65@AEA_K@Z
     ??$construct@UViableSubstitution@strings_internal@absl@@AEAVstring_view@3@AEBV43@AEA_K@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@SAXAEAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PEAUViableSubstitution@strings_internal@absl@@AEAVstring_view@6@AEBV76@AEA_K@Z
     ??$construct@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IEAAX$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
@@ -531,8 +550,11 @@
     ??$distance@PEBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YA_JPEBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$distance@V?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@01@0@Z
     ??$distance@V?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@01@0@Z
+    ??$distance@V?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@YA_JV?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@01@0@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
     ??$emplace_back@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$emplace_back@AEBH@?$InlinedVector@H$0CP@V?$allocator@H@__1@std@@@absl@@QEAAAEAHAEBH@Z
     ??$emplace_back@AEBQEAUCordRep@cord_internal@absl@@@?$InlinedVector@PEAUCordRep@cord_internal@absl@@$01V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QEAAAEAPEAUCordRep@cord_internal@1@AEBQEAU231@@Z
@@ -577,6 +599,7 @@
     ??$forward@AEBQEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAAEBQEBVImpl@time_zone@cctz@time_internal@absl@@AEBQEBV23456@@Z
     ??$forward@AEBUHashtablezInfo@container_internal@absl@@@__1@std@@YAAEBUHashtablezInfo@container_internal@absl@@AEBU234@@Z
     ??$forward@AEBUPayload@status_internal@absl@@@__1@std@@YAAEBUPayload@status_internal@absl@@AEBU234@@Z
+    ??$forward@AEBUTransition@cctz@time_internal@absl@@@__1@std@@YAAEBUTransition@cctz@time_internal@absl@@AEBU2345@@Z
     ??$forward@AEBV?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@YAAEBV?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@AEBV123@@Z
     ??$forward@AEBV?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@YAAEBV?$allocator@UPayload@status_internal@absl@@@__1@std@@AEBV123@@Z
     ??$forward@AEBVCord@absl@@@__1@std@@YAAEBVCord@absl@@AEBV23@@Z
@@ -598,6 +621,7 @@
     ??$forward@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@__1@std@@YA$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@01@@Z@AEAU2?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@34@QEAA@0@Z@@Z
     ??$forward@USubRange@absl@@@__1@std@@YA$$QEAUSubRange@absl@@AEAU23@@Z
     ??$forward@UTransition@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransition@cctz@time_internal@absl@@AEAU2345@@Z
+    ??$forward@UTransitionType@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransitionType@cctz@time_internal@absl@@AEAU2345@@Z
     ??$forward@V?$Span@I@absl@@@__1@std@@YA$$QEAV?$Span@I@absl@@AEAV23@@Z
     ??$forward@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@01@AEAV201@@Z
     ??$forward@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@01@AEAV201@@Z
@@ -658,6 +682,7 @@
     ??$move@AEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@__1@std@@YA$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@01@@Z@AEAU2?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@34@QEAA@0@Z@@Z
     ??$move@AEAUSubRange@absl@@@__1@std@@YA$$QEAUSubRange@absl@@AEAU23@@Z
     ??$move@AEAUTransition@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransition@cctz@time_internal@absl@@AEAU2345@@Z
+    ??$move@AEAUTransitionType@cctz@time_internal@absl@@@__1@std@@YA$$QEAUTransitionType@cctz@time_internal@absl@@AEAU2345@@Z
     ??$move@AEAUViableSubstitution@strings_internal@absl@@@__1@std@@YA$$QEAUViableSubstitution@strings_internal@absl@@AEAU234@@Z
     ??$move@AEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@01@AEAV201@@Z
     ??$move@AEAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@__1@std@@YA$$QEAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@01@AEAV201@@Z
@@ -666,8 +691,10 @@
     ??$move@AEAVInlineRep@Cord@absl@@@__1@std@@YA$$QEAVInlineRep@Cord@absl@@AEAV234@@Z
     ??$move@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$move@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$move@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$move_backward@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV12345@@__1@std@@YAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@PEAPEAPEBV23456@00@Z
     ??$move_backward@PEAUTransition@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransition@cctz@time_internal@absl@@PEAU2345@00@Z
+    ??$move_backward@PEAUTransitionType@cctz@time_internal@absl@@PEAU1234@@__1@std@@YAPEAUTransitionType@cctz@time_internal@absl@@PEAU2345@00@Z
     ??$reset@PEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@?$unique_ptr@$$BY0A@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QEAAXPEAPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@@Z
     ??$swap@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAXAEAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@0@Z
     ??$swap@PEAPEAUCordRep@cord_internal@absl@@@__1@std@@YAXAEAPEAPEAUCordRep@cord_internal@absl@@0@Z
@@ -841,6 +868,7 @@
     ??0?$move_iterator@PEAUPayload@status_internal@absl@@@__1@std@@QEAA@PEAUPayload@status_internal@absl@@@Z
     ??0?$move_iterator@PEAUSubRange@absl@@@__1@std@@QEAA@PEAUSubRange@absl@@@Z
     ??0?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEAA@PEAUTransition@cctz@time_internal@absl@@@Z
+    ??0?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEAA@PEAUTransitionType@cctz@time_internal@absl@@@Z
     ??0?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@QEAA@XZ
     ??0?$optional@VCord@absl@@@absl@@QEAA@Unullopt_t@1@@Z
     ??0?$optional_data@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@optional_internal@absl@@IEAA@XZ
@@ -917,6 +945,8 @@
     ??0Refcount@cord_internal@absl@@QEAA@XZ
     ??0Rep@GraphCycles@synchronization_internal@absl@@QEAA@XZ
     ??0SchedulingHelper@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z
+    ??0ScopedDisable@SchedulingGuard@base_internal@absl@@QEAA@XZ
+    ??0ScopedEnable@SchedulingGuard@base_internal@absl@@QEAA@XZ
     ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z
     ??0SpinLockHolder@base_internal@absl@@QEAA@PEAVSpinLock@12@@Z
     ??0Status@absl@@QEAA@W4StatusCode@1@Vstring_view@1@@Z
@@ -1002,6 +1032,7 @@
     ??1?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
     ??1?$__split_buffer@UViableSubstitution@strings_internal@absl@@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
     ??1?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
+    ??1?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA@XZ
     ??1?$__vector_base@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@IEAA@XZ
     ??1?$__vector_base@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@IEAA@XZ
     ??1?$__vector_base@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@IEAA@XZ
@@ -1050,6 +1081,8 @@
     ??1Refcount@cord_internal@absl@@QEAA@XZ
     ??1Rep@GraphCycles@synchronization_internal@absl@@QEAA@XZ
     ??1SchedulingHelper@base_internal@absl@@QEAA@XZ
+    ??1ScopedDisable@SchedulingGuard@base_internal@absl@@QEAA@XZ
+    ??1ScopedEnable@SchedulingGuard@base_internal@absl@@QEAA@XZ
     ??1SpinLockHolder@base_internal@absl@@QEAA@XZ
     ??1StatusRep@status_internal@absl@@QEAA@XZ
     ??1Storage@?$FixedArray@PEAUCordRep@cord_internal@absl@@$0?0V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QEAA@XZ
@@ -1176,6 +1209,7 @@
     ??D?$move_iterator@PEAUPayload@status_internal@absl@@@__1@std@@QEBA$$QEAUPayload@status_internal@absl@@XZ
     ??D?$move_iterator@PEAUSubRange@absl@@@__1@std@@QEBA$$QEAUSubRange@absl@@XZ
     ??D?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEBA$$QEAUTransition@cctz@time_internal@absl@@XZ
+    ??D?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBA$$QEAUTransitionType@cctz@time_internal@absl@@XZ
     ??D?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@QEGAAAEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@XZ
     ??D?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEBAAEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@XZ
     ??DChunkIterator@Cord@absl@@QEBA?AVstring_view@2@XZ
@@ -1190,6 +1224,7 @@
     ??E?$move_iterator@PEAUPayload@status_internal@absl@@@__1@std@@QEAAAEAV012@XZ
     ??E?$move_iterator@PEAUSubRange@absl@@@__1@std@@QEAAAEAV012@XZ
     ??E?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEAAAEAV012@XZ
+    ??E?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEAAAEAV012@XZ
     ??EChunkIterator@Cord@absl@@QEAAAEAV012@XZ
     ??Euint128@absl@@QEAAAEAV01@XZ
     ??Gabsl@@YA?AVDuration@0@V10@0@Z
@@ -1402,7 +1437,6 @@
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ
     ?CheckLengthInternal@string_view@absl@@CA_K_K@Z
     ?CheckNode@CordForest@absl@@CAXPEAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@AEBAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUTransitionType@234@H_N0@Z
     ?Chunks@Cord@absl@@QEBA?AVChunkRange@12@XZ
     ?CityHash32@hash_internal@absl@@YAIPEBD_K@Z
     ?CityHash64@hash_internal@absl@@YA_KPEBD_K@Z
@@ -1524,7 +1558,7 @@
     ?ErasePayload@Status@absl@@QEAA_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QEBA_NXZ
     ?Excess@str_format_internal@absl@@YA_K_K0@Z
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPEBDH@Z
@@ -1715,6 +1749,7 @@
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetTagForChar@str_format_internal@absl@@YA?AVConvTag@12@D@Z
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPEAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NH_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAE@Z
     ?GetWaiter@Waiter@synchronization_internal@absl@@SAPEAV123@PEAUThreadIdentity@base_internal@3@@Z
     ?GetWeekday@absl@@YA?AW4weekday@detail@cctz@time_internal@1@V?$civil_time@Usecond_tag@time_internal@absl@@@3451@@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QEBAIH@Z
@@ -1788,7 +1823,7 @@
     ?Load@?$AtomicHook@P6A?AV?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@Vstring_view@2@AEBVCord@2@@Z@base_internal@absl@@QEBAP6A?AV?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@3@Vstring_view@3@AEBVCord@3@@ZXZ
     ?Load@?$AtomicHook@P6A_NW4LogSeverity@absl@@PEBDHPEAPEADPEAH@Z@base_internal@absl@@QEBAP6A_NW4LogSeverity@3@PEBDHPEAPEADPEAH@ZXZ
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NPEAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z
@@ -1841,6 +1876,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QEAAXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AEAAXHPEBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AEAAXHPEBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?Name@Impl@time_zone@cctz@time_internal@absl@@QEBAAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@XZ
     ?Nanoseconds@absl@@YA?AVDuration@1@_J@Z
     ?NegateAndSubtractOne@time_internal@absl@@YA_J_J@Z
@@ -2208,6 +2244,7 @@
     ?ZeroDuration@absl@@YA?AVDuration@1@XZ
     ?__add_back_capacity@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
     ?__addr@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAPEAUTransition@cctz@time_internal@absl@@XZ
+    ?__addr@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAPEAUTransitionType@cctz@time_internal@absl@@XZ
     ?__alloc@?$__bucket_list_deallocator@V?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@__1@std@@@__1@std@@QEAAAEAV?$allocator@PEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@XZ
     ?__alloc@?$__deque_base@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@IEAAAEAV?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ
     ?__alloc@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAAEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ
@@ -2406,6 +2443,7 @@
     ?__max_size@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@CA_KU?$integral_constant@_N$00@23@AEBV?$allocator@UViableSubstitution@strings_internal@absl@@@23@@Z
     ?__max_size@?$allocator_traits@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@CA_KU?$integral_constant@_N$00@23@AEBV?$allocator@VFormatArgImpl@str_format_internal@absl@@@23@@Z
     ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXPEAUTransition@cctz@time_internal@absl@@00@Z
+    ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXPEAUTransitionType@cctz@time_internal@absl@@00@Z
     ?__node_alloc@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAAEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@23@XZ
     ?__ptr@?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@QEAAPEAU123@XZ
     ?__recommend@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEBA_K_K@Z
@@ -2419,6 +2457,7 @@
     ?__swap_out_circular_buffer@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UConversionItem@ParsedFormatBase@str_format_internal@absl@@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransition@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransitionType@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UViableSubstitution@strings_internal@absl@@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@23@@Z
     ?__upcast@?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@QEAAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@XZ
@@ -2484,8 +2523,10 @@
     ?base@?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBAPEAUTransitionType@cctz@time_internal@absl@@XZ
     ?base@?$__wrap_iter@PEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@QEBAPEBUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ
     ?base@?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@__1@std@@QEBAPEBUTransition@cctz@time_internal@absl@@XZ
+    ?base@?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBAPEBUTransitionType@cctz@time_internal@absl@@XZ
     ?base@?$move_iterator@PEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@QEBAPEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ
     ?base@?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__1@std@@QEBAPEAUTransition@cctz@time_internal@absl@@XZ
+    ?base@?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__1@std@@QEBAPEAUTransitionType@cctz@time_internal@absl@@XZ
     ?begin@?$InlinedVector@PEAUCordRep@cord_internal@absl@@$0CP@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QEAAPEAPEAUCordRep@cord_internal@2@XZ
     ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ
     ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ
@@ -2749,6 +2790,7 @@
     ?get@?$Storage@_K$00$0A@@internal_compressed_tuple@container_internal@absl@@QEGBAAEB_KXZ
     ?get@?$Storage@_K$0A@$0A@@internal_compressed_tuple@container_internal@absl@@QEGBAAEB_KXZ
     ?get@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAAEAUTransition@cctz@time_internal@absl@@XZ
+    ?get@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAAEAUTransitionType@cctz@time_internal@absl@@XZ
     ?get@?$unique_ptr@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@QEBAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@XZ
     ?get@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@__1@std@@QEBAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@XZ
     ?get@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEBAPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@XZ
@@ -2877,6 +2919,7 @@
     ?push_back@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_back@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
     ?push_back@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
+    ?push_back@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?raw_code@Status@absl@@QEBAHXZ
@@ -2894,6 +2937,7 @@
     ?rend@string_view@absl@@QEBA?AV?$reverse_iterator@PEBD@__1@std@@XZ
     ?replace_tree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reset@?$unique_ptr@$$CBVImpl@time_zone@cctz@time_internal@absl@@U?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?reset@?$unique_ptr@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$__allocator_destructor@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@QEAAXPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_x64_rel.def b/third_party/abseil-cpp/symbols_x64_rel.def
index a7d785e..1e301a4 100644
--- a/third_party/abseil-cpp/symbols_x64_rel.def
+++ b/third_party/abseil-cpp/symbols_x64_rel.def
@@ -62,12 +62,15 @@
     ??$ToChronoDuration@V?$duration@JV?$ratio@$0OBA@$00@__1@std@@@chrono@__1@std@@@time_internal@absl@@YA?AV?$duration@JV?$ratio@$0OBA@$00@__1@std@@@chrono@__1@std@@VDuration@1@@Z
     ??$__emplace_back_slow_path@AEAVstring_view@absl@@AEBV12@AEA_K@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAVstring_view@absl@@AEBV34@AEA_K@Z
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
+    ??$__push_back_slow_path@AEBUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ??$__push_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__upper_bound@AEAUByCivilTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByCivilTime@2345@@Z
     ??$assign@PEBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@QEAAXPEBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$assign@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IEAAX$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
     ??$find@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@Vstring_view@2@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@XZ
@@ -226,7 +229,6 @@
     ?Ceil@absl@@YA?AVDuration@1@V21@0@Z
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ
     ?CheckNode@CordForest@absl@@CAXPEAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@AEBAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUTransitionType@234@H_N0@Z
     ?CityHash32@hash_internal@absl@@YAIPEBD_K@Z
     ?CityHash64@hash_internal@absl@@YA_KPEBD_K@Z
     ?CityHash64WithSeed@hash_internal@absl@@YA_KPEBD_K1@Z
@@ -297,7 +299,7 @@
     ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z
     ?ErasePayload@Status@absl@@QEAA_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QEBA_NXZ
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPEBDH@Z
@@ -381,6 +383,7 @@
     ?GetStride@ExponentialBiased@base_internal@absl@@QEAA_J_J@Z
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPEAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NH_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAE@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QEBAIH@Z
     ?GetWord@?$BigUnsigned@$0FE@@strings_internal@absl@@QEBAIH@Z
     ?Global@HashtablezSampler@container_internal@absl@@SAAEAV123@XZ
@@ -423,7 +426,7 @@
     ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@W4LengthMod@12@@Z
     ?LengthToTag@CordTestAccess@strings_internal@absl@@SAE_K@Z
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NPEAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z
@@ -456,6 +459,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QEAAXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AEAAXHPEBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AEAAXHPEBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPEAUArena@123@H@Z
     ?NewExternalWithUninitializedReleaser@cord_internal@absl@@YA?AUExternalRepReleaserPair@12@Vstring_view@2@P6A_KPEAX0@Z_K@Z
     ?NewRep@Status@absl@@CA_KW4StatusCode@2@Vstring_view@2@V?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@@Z
@@ -696,6 +700,7 @@
     ?__invoke@<lambda_1>@?0???$NewExternalRep@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@cord_internal@absl@@YAPEAUCordRep@23@Vstring_view@3@$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@3@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@Z@CA?A?<auto>@@PEAX0@Z
     ?__rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AEAAX_K@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransition@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransitionType@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__vallocate@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAX_K@Z
     ?__vallocate@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAX_K@Z
     ?clear@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAXXZ
@@ -745,6 +750,7 @@
     ?raw_code@Status@absl@@QEBAHXZ
     ?rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reset@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@__1@std@@QEAAXPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@@Z
     ?reset@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAAXPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_x64_rel_asan.def b/third_party/abseil-cpp/symbols_x64_rel_asan.def
index 507709e0..90417beb 100644
--- a/third_party/abseil-cpp/symbols_x64_rel_asan.def
+++ b/third_party/abseil-cpp/symbols_x64_rel_asan.def
@@ -63,13 +63,16 @@
     ??$__construct_at_end@PEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXPEBQEAUCordRep@cord_internal@absl@@0_K@Z
     ??$__construct_at_end@PEBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAXPEBVFormatArgImpl@str_format_internal@absl@@0_K@Z
     ??$__construct_one_at_end@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
+    ??$__construct_one_at_end@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXXZ
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QEAV?$tuple@$$V@12@@Z
     ??$__push_back_slow_path@AEBQEAUCordRep@cord_internal@absl@@@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXAEBQEAUCordRep@cord_internal@absl@@@Z
     ??$__upper_bound@AEAUByCivilTime@Transition@cctz@time_internal@absl@@PEBU2345@U2345@@__1@std@@YAPEBUTransition@cctz@time_internal@absl@@PEBU2345@0AEBU2345@AEAUByCivilTime@2345@@Z
     ??$assign@PEBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@QEAAXPEBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$assign@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IEAAX$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAA?AV?$__wrap_iter@PEAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PEBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXXZ
     ??$find@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAA?AV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@Vstring_view@2@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@XZ
@@ -236,7 +239,6 @@
     ?Ceil@absl@@YA?AVDuration@1@V21@0@Z
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ
     ?CheckNode@CordForest@absl@@CAXPEAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@AEBAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUTransitionType@234@H_N0@Z
     ?CityHash32@hash_internal@absl@@YAIPEBD_K@Z
     ?CityHash64@hash_internal@absl@@YA_KPEBD_K@Z
     ?CityHash64WithSeed@hash_internal@absl@@YA_KPEBD_K1@Z
@@ -306,7 +308,7 @@
     ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@inlined_vector_internal@absl@@QEAAPEAUPayload@status_internal@3@PEBU453@0@Z
     ?ErasePayload@Status@absl@@QEAA_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QEBA_NXZ
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAAXAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@AEBUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPEBDH@Z
@@ -390,6 +392,7 @@
     ?GetStride@ExponentialBiased@base_internal@absl@@QEAA_J_J@Z
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPEAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NH_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAE@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QEBAIH@Z
     ?GetWord@?$BigUnsigned@$0FE@@strings_internal@absl@@QEBAIH@Z
     ?Global@HashtablezSampler@container_internal@absl@@SAAEAV123@XZ
@@ -432,7 +435,7 @@
     ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@W4LengthMod@12@@Z
     ?LengthToTag@CordTestAccess@strings_internal@absl@@SAE_K@Z
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NPEAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QEAA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NAEBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@AEBA?AUabsolute_lookup@time_zone@234@_JAEBUTransition@234@@Z
@@ -465,6 +468,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QEAAXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AEAAXHPEBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AEAAXHPEBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPEAUArena@123@H@Z
     ?NewExternalWithUninitializedReleaser@cord_internal@absl@@YA?AUExternalRepReleaserPair@12@Vstring_view@2@P6A_KPEAX0@Z_K@Z
     ?NewRep@Status@absl@@CA_KW4StatusCode@2@Vstring_view@2@V?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@@Z
@@ -725,11 +729,13 @@
     ?__deallocate_node@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AEAAXPEAU?$__hash_node_base@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@23@@Z
     ?__invoke@<lambda_1>@?0???$NewExternalRep@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@cord_internal@absl@@YAPEAUCordRep@23@Vstring_view@3@$$QEAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@3@QEAA@$$QEAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@Z@CA?A?<auto>@@PEAX0@Z
     ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXPEAUTransition@cctz@time_internal@absl@@00@Z
+    ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXPEAUTransitionType@cctz@time_internal@absl@@00@Z
     ?__rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AEAAX_K@Z
     ?__swap_out_circular_buffer@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@PEAUCordRep@cord_internal@absl@@AEAV?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UConversionItem@ParsedFormatBase@str_format_internal@absl@@AEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransition@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAPEAUTransitionType@cctz@time_internal@absl@@AEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PEAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AEAAXAEAU?$__split_buffer@UViableSubstitution@strings_internal@absl@@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@23@@Z
     ?__vallocate@?$vector@PEAUCordRep@cord_internal@absl@@V?$allocator@PEAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AEAAX_K@Z
@@ -778,11 +784,13 @@
     ?push_back@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_back@?$deque@PEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_back@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
+    ?push_back@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBUTransition@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@AEAV?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAXAEBQEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PEAPEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX$$QEAPEAPEBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?raw_code@Status@absl@@QEBAHXZ
     ?rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QEAAX_K@Z
     ?reset@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@__1@std@@@__1@std@@@23@@__1@std@@QEAAXPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PEAX@23@@Z
     ?reset@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QEAAXPEAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_x86_dbg.def b/third_party/abseil-cpp/symbols_x86_dbg.def
index c10054c8..8d50a8e4 100644
--- a/third_party/abseil-cpp/symbols_x86_dbg.def
+++ b/third_party/abseil-cpp/symbols_x86_dbg.def
@@ -28,6 +28,7 @@
     ??$?0$$TX@?$__compressed_pair_elem@PAUViableSubstitution@strings_internal@absl@@$0A@$0A@@__1@std@@QAE@$$QA$$T@Z
     ??$?0$$TX@?$__compressed_pair_elem@PAVFormatArgImpl@str_format_internal@absl@@$0A@$0A@@__1@std@@QAE@$$QA$$T@Z
     ??$?0$$V@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE@AAV?$allocator@UTransition@cctz@time_internal@absl@@@12@@Z
+    ??$?0$$V@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$?0$00X@?$__compressed_pair@U?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@23@@__1@std@@QAE@XZ
     ??$?0$00X@?$unique_ptr@$$BY0A@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QAE@XZ
     ??$?0$00X@?$unique_ptr@$$CBVImpl@time_zone@cctz@time_internal@absl@@U?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE@PBVImpl@time_zone@cctz@time_internal@absl@@@Z
@@ -99,6 +100,7 @@
     ??$?0PAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@$00@?$__compressed_pair@PAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QAE@$$QAPAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@12@@Z
     ??$?0PAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@X@?$__compressed_pair_elem@PAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@$0A@$0A@@__1@std@@QAE@$$QAPAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@12@@Z
     ??$?0PAUTransition@cctz@time_internal@absl@@@?$__wrap_iter@PBUTransition@cctz@time_internal@absl@@@__1@std@@QAE@ABV?$__wrap_iter@PAUTransition@cctz@time_internal@absl@@@12@PAX@Z
+    ??$?0PAUTransitionType@cctz@time_internal@absl@@@?$__wrap_iter@PBUTransitionType@cctz@time_internal@absl@@@__1@std@@QAE@ABV?$__wrap_iter@PAUTransitionType@cctz@time_internal@absl@@@12@PAX@Z
     ??$?0PAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$00@?$__compressed_pair@PAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QAE@$$QAPAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
     ??$?0PAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@?$__compressed_pair@PAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QAE@$$QAPAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$$QAU?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@12@@Z
     ??$?0PAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@X@?$__compressed_pair_elem@PAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@$0A@$0A@@__1@std@@QAE@$$QAPAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
@@ -172,7 +174,9 @@
     ??$?D_J@absl@@YA?AVDuration@0@_JV10@@Z
     ??$?GPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV01234@@__1@std@@YAHABV?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@01@0@Z
     ??$?GPAUTransition@cctz@time_internal@absl@@PAU0123@@__1@std@@YAHABV?$move_iterator@PAUTransition@cctz@time_internal@absl@@@01@0@Z
+    ??$?GPAUTransitionType@cctz@time_internal@absl@@PAU0123@@__1@std@@YAHABV?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0@Z
     ??$?GPBUTransition@cctz@time_internal@absl@@PAU0123@@__1@std@@YAHABV?$__wrap_iter@PBUTransition@cctz@time_internal@absl@@@01@ABV?$__wrap_iter@PAUTransition@cctz@time_internal@absl@@@01@@Z
+    ??$?GPBUTransitionType@cctz@time_internal@absl@@PAU0123@@__1@std@@YAHABV?$__wrap_iter@PBUTransitionType@cctz@time_internal@absl@@@01@ABV?$__wrap_iter@PAUTransitionType@cctz@time_internal@absl@@@01@@Z
     ??$?K_J@absl@@YA?AVDuration@0@V10@_J@Z
     ??$?MUsecond_tag@detail@cctz@time_internal@absl@@U01234@@detail@cctz@time_internal@absl@@YA_NABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z
     ??$?NUsecond_tag@detail@cctz@time_internal@absl@@U01234@@detail@cctz@time_internal@absl@@YA_NABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@0123@0@Z
@@ -378,23 +382,29 @@
     ??$__construct@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@ABUpiecewise_construct_t@23@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@12@PAU?$pair@$$CBV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@12@ABUpiecewise_construct_t@12@$$QAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QAV?$tuple@$$V@12@@Z
     ??$__construct@UConversionItem@ParsedFormatBase@str_format_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@$$QAU5678@@Z
     ??$__construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@@Z
+    ??$__construct@UTransition@cctz@time_internal@absl@@ABU1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@ABU5678@@Z
     ??$__construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@$$QAU5678@@Z
     ??$__construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PAUTransitionType@cctz@time_internal@absl@@@Z
+    ??$__construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PAUTransitionType@cctz@time_internal@absl@@$$QAU5678@@Z
     ??$__construct@UViableSubstitution@strings_internal@absl@@AAVstring_view@3@ABV43@AAI@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@CAXU?$integral_constant@_N$00@12@AAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PAUViableSubstitution@strings_internal@absl@@AAVstring_view@7@ABV87@AAI@Z
     ??$__construct_at_end@PBQAUCordRep@cord_internal@absl@@@?$vector@PAUCordRep@cord_internal@absl@@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AAEXPBQAUCordRep@cord_internal@absl@@0I@Z
     ??$__construct_at_end@PBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AAEXPBVFormatArgImpl@str_format_internal@absl@@0I@Z
     ??$__construct_at_end@V?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@AAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXV?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@12@0@Z
     ??$__construct_at_end@V?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@UTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXV?$move_iterator@PAUTransition@cctz@time_internal@absl@@@12@0@Z
+    ??$__construct_at_end@V?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXV?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@12@0@Z
     ??$__construct_backward_with_exception_guarantees@PAUCordRep@cord_internal@absl@@@?$allocator_traits@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@PAUCordRep@cord_internal@absl@@@12@PAPAUCordRep@cord_internal@absl@@1AAPAPAU456@@Z
     ??$__construct_backward_with_exception_guarantees@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@1AAPAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UTransition@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@1AAPAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UTransitionType@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PAUTransitionType@cctz@time_internal@absl@@1AAPAU4567@@Z
     ??$__construct_backward_with_exception_guarantees@UViableSubstitution@strings_internal@absl@@@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PAUViableSubstitution@strings_internal@absl@@1AAPAU456@@Z
     ??$__construct_forward_with_exception_guarantees@UTransition@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@1AAPAU4567@@Z
+    ??$__construct_forward_with_exception_guarantees@UTransitionType@cctz@time_internal@absl@@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PAUTransitionType@cctz@time_internal@absl@@1AAPAU4567@@Z
     ??$__construct_node_hash@ABUpiecewise_construct_t@__1@std@@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AAE?AV?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@23@@12@IABUpiecewise_construct_t@12@$$QAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QAV?$tuple@$$V@12@@Z
     ??$__construct_one_at_end@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXXZ
+    ??$__construct_one_at_end@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXXZ
     ??$__construct_one_at_end@AAVstring_view@absl@@ABV12@AAI@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AAEXAAVstring_view@absl@@ABV34@AAI@Z
     ??$__construct_one_at_end@ABQAUCordRep@cord_internal@absl@@@?$vector@PAUCordRep@cord_internal@absl@@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AAEXABQAUCordRep@cord_internal@absl@@@Z
+    ??$__construct_one_at_end@ABUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXABUTransition@cctz@time_internal@absl@@@Z
     ??$__construct_one_at_end@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AAEX$$QAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__construct_range_forward@$$CBVFormatArgImpl@str_format_internal@absl@@V123@V123@V123@@?$allocator_traits@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@VFormatArgImpl@str_format_internal@absl@@@12@PBVFormatArgImpl@str_format_internal@absl@@1AAPAV456@@Z
     ??$__construct_range_forward@QAUCordRep@cord_internal@absl@@PAU123@PAU123@PAU123@@?$allocator_traits@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@PAUCordRep@cord_internal@absl@@@12@PBQAUCordRep@cord_internal@absl@@1AAPAPAU456@@Z
@@ -420,14 +430,18 @@
     ??$__distance@PBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAHPBVFormatArgImpl@str_format_internal@absl@@0Urandom_access_iterator_tag@01@@Z
     ??$__distance@V?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@YAHV?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
     ??$__distance@V?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@YAHV?$move_iterator@PAUTransition@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
+    ??$__distance@V?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@YAHV?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0Urandom_access_iterator_tag@01@@Z
     ??$__emplace_back_slow_path@AAVstring_view@absl@@ABV12@AAI@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AAEXAAVstring_view@absl@@ABV34@AAI@Z
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@ABUpiecewise_construct_t@23@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@_N@12@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@ABUpiecewise_construct_t@12@$$QAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QAV?$tuple@$$V@12@@Z
     ??$__lower_bound@AAUByUnixTime@Transition@cctz@time_internal@absl@@PBU2345@U2345@@__1@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@AAUByUnixTime@2345@@Z
     ??$__move@PAPBVImpl@time_zone@cctz@time_internal@absl@@PAPBV12345@@__1@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@00@Z
     ??$__move@UTransition@cctz@time_internal@absl@@U1234@@__1@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@00@Z
+    ??$__move@UTransitionType@cctz@time_internal@absl@@U1234@@__1@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@00@Z
     ??$__move_backward@PAPBVImpl@time_zone@cctz@time_internal@absl@@PAPBV12345@@__1@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@00@Z
     ??$__move_backward@UTransition@cctz@time_internal@absl@@U1234@@__1@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@00@Z
+    ??$__move_backward@UTransitionType@cctz@time_internal@absl@@U1234@@__1@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@00@Z
     ??$__push_back_slow_path@ABQAUCordRep@cord_internal@absl@@@?$vector@PAUCordRep@cord_internal@absl@@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@AAEXABQAUCordRep@cord_internal@absl@@@Z
+    ??$__push_back_slow_path@ABUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXABUTransition@cctz@time_internal@absl@@@Z
     ??$__push_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AAEX$$QAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__to_raw_pointer@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@@Z
     ??$__to_raw_pointer@PAUCordRep@cord_internal@absl@@@__1@std@@YAPAPAUCordRep@cord_internal@absl@@PAPAU234@@Z
@@ -438,6 +452,7 @@
     ??$__to_raw_pointer@VFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPAVFormatArgImpl@str_format_internal@absl@@PAV234@@Z
     ??$__unwrap_iter@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@@Z
     ??$__unwrap_iter@PAUTransition@cctz@time_internal@absl@@@__1@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@@Z
+    ??$__unwrap_iter@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@@Z
     ??$__unwrap_iter@PAVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPAVFormatArgImpl@str_format_internal@absl@@PAV234@@Z
     ??$__unwrap_iter@PBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAPBVFormatArgImpl@str_format_internal@absl@@PBV234@@Z
     ??$__upper_bound@AAUByCivilTime@Transition@cctz@time_internal@absl@@PBU2345@U2345@@__1@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@AAUByCivilTime@2345@@Z
@@ -489,10 +504,14 @@
     ??$construct@USubRange@absl@@U12@@?$allocator_traits@V?$allocator@USubRange@absl@@@__1@std@@@absl@@SAXAAV?$allocator@USubRange@absl@@@__1@std@@PAUSubRange@1@$$QAU51@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QAEXPAUTransition@cctz@time_internal@absl@@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@@Z
+    ??$construct@UTransition@cctz@time_internal@absl@@ABU1234@@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QAEXPAUTransition@cctz@time_internal@absl@@ABU3456@@Z
+    ??$construct@UTransition@cctz@time_internal@absl@@ABU1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@ABU4567@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@QAEXPAUTransition@cctz@time_internal@absl@@$$QAU3456@@Z
     ??$construct@UTransition@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransition@cctz@time_internal@absl@@@12@PAUTransition@cctz@time_internal@absl@@$$QAU4567@@Z
     ??$construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@QAEXPAUTransitionType@cctz@time_internal@absl@@@Z
     ??$construct@UTransitionType@cctz@time_internal@absl@@$$V@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PAUTransitionType@cctz@time_internal@absl@@@Z
+    ??$construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@QAEXPAUTransitionType@cctz@time_internal@absl@@$$QAU3456@@Z
+    ??$construct@UTransitionType@cctz@time_internal@absl@@U1234@@?$allocator_traits@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UTransitionType@cctz@time_internal@absl@@@12@PAUTransitionType@cctz@time_internal@absl@@$$QAU4567@@Z
     ??$construct@UViableSubstitution@strings_internal@absl@@AAVstring_view@3@ABV43@AAI@?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@QAEXPAUViableSubstitution@strings_internal@absl@@AAVstring_view@5@ABV65@AAI@Z
     ??$construct@UViableSubstitution@strings_internal@absl@@AAVstring_view@3@ABV43@AAI@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@SAXAAV?$allocator@UViableSubstitution@strings_internal@absl@@@12@PAUViableSubstitution@strings_internal@absl@@AAVstring_view@6@ABV76@AAI@Z
     ??$construct@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IAEX$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
@@ -529,8 +548,11 @@
     ??$distance@PBVFormatArgImpl@str_format_internal@absl@@@__1@std@@YAHPBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$distance@V?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@YAHV?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@01@0@Z
     ??$distance@V?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@YAHV?$move_iterator@PAUTransition@cctz@time_internal@absl@@@01@0@Z
+    ??$distance@V?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@YAHV?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@01@0@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE?AV?$__wrap_iter@PAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE?AV?$__wrap_iter@PAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXXZ
     ??$emplace_back@AAVstring_view@absl@@ABV12@AAI@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QAEXAAVstring_view@absl@@ABV34@AAI@Z
     ??$emplace_back@ABH@?$InlinedVector@H$0CP@V?$allocator@H@__1@std@@@absl@@QAEAAHABH@Z
     ??$emplace_back@ABQAUCordRep@cord_internal@absl@@@?$InlinedVector@PAUCordRep@cord_internal@absl@@$01V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QAEAAPAUCordRep@cord_internal@1@ABQAU231@@Z
@@ -576,6 +598,7 @@
     ??$forward@ABQBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAABQBVImpl@time_zone@cctz@time_internal@absl@@ABQBV23456@@Z
     ??$forward@ABUHashtablezInfo@container_internal@absl@@@__1@std@@YAABUHashtablezInfo@container_internal@absl@@ABU234@@Z
     ??$forward@ABUPayload@status_internal@absl@@@__1@std@@YAABUPayload@status_internal@absl@@ABU234@@Z
+    ??$forward@ABUTransition@cctz@time_internal@absl@@@__1@std@@YAABUTransition@cctz@time_internal@absl@@ABU2345@@Z
     ??$forward@ABV?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@absl@@YAABV?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@ABV123@@Z
     ??$forward@ABV?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@YAABV?$allocator@UPayload@status_internal@absl@@@__1@std@@ABV123@@Z
     ??$forward@ABVCord@absl@@@__1@std@@YAABVCord@absl@@ABV23@@Z
@@ -596,6 +619,7 @@
     ??$forward@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QAE@$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@__1@std@@YA$$QAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QAE@$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@01@@Z@AAU2?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@34@QAE@0@Z@@Z
     ??$forward@USubRange@absl@@@__1@std@@YA$$QAUSubRange@absl@@AAU23@@Z
     ??$forward@UTransition@cctz@time_internal@absl@@@__1@std@@YA$$QAUTransition@cctz@time_internal@absl@@AAU2345@@Z
+    ??$forward@UTransitionType@cctz@time_internal@absl@@@__1@std@@YA$$QAUTransitionType@cctz@time_internal@absl@@AAU2345@@Z
     ??$forward@V?$Span@I@absl@@@__1@std@@YA$$QAV?$Span@I@absl@@AAV23@@Z
     ??$forward@V?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@YA$$QAV?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@01@AAV201@@Z
     ??$forward@V?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@YA$$QAV?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@01@AAV201@@Z
@@ -656,6 +680,7 @@
     ??$move@AAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QAE@$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@__1@std@@YA$$QAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QAE@$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@01@@Z@AAU2?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@34@QAE@0@Z@@Z
     ??$move@AAUSubRange@absl@@@__1@std@@YA$$QAUSubRange@absl@@AAU23@@Z
     ??$move@AAUTransition@cctz@time_internal@absl@@@__1@std@@YA$$QAUTransition@cctz@time_internal@absl@@AAU2345@@Z
+    ??$move@AAUTransitionType@cctz@time_internal@absl@@@__1@std@@YA$$QAUTransitionType@cctz@time_internal@absl@@AAU2345@@Z
     ??$move@AAUViableSubstitution@strings_internal@absl@@@__1@std@@YA$$QAUViableSubstitution@strings_internal@absl@@AAU234@@Z
     ??$move@AAV?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@YA$$QAV?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@01@AAV201@@Z
     ??$move@AAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@@__1@std@@YA$$QAV?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@01@AAV201@@Z
@@ -664,8 +689,10 @@
     ??$move@AAVInlineRep@Cord@absl@@@__1@std@@YA$$QAVInlineRep@Cord@absl@@AAV234@@Z
     ??$move@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@__1@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@00@Z
     ??$move@PAUTransition@cctz@time_internal@absl@@PAU1234@@__1@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@00@Z
+    ??$move@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@__1@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@00@Z
     ??$move_backward@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV12345@@__1@std@@YAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@PAPAPBV23456@00@Z
     ??$move_backward@PAUTransition@cctz@time_internal@absl@@PAU1234@@__1@std@@YAPAUTransition@cctz@time_internal@absl@@PAU2345@00@Z
+    ??$move_backward@PAUTransitionType@cctz@time_internal@absl@@PAU1234@@__1@std@@YAPAUTransitionType@cctz@time_internal@absl@@PAU2345@00@Z
     ??$reset@PAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@?$unique_ptr@$$BY0A@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@V?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@@23@@__1@std@@QAEXPAPAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@12@@Z
     ??$swap@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@YAXAAPAPAPBVImpl@time_zone@cctz@time_internal@absl@@0@Z
     ??$swap@PAPAUCordRep@cord_internal@absl@@@__1@std@@YAXAAPAPAUCordRep@cord_internal@absl@@0@Z
@@ -839,6 +866,7 @@
     ??0?$move_iterator@PAUPayload@status_internal@absl@@@__1@std@@QAE@PAUPayload@status_internal@absl@@@Z
     ??0?$move_iterator@PAUSubRange@absl@@@__1@std@@QAE@PAUSubRange@absl@@@Z
     ??0?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@QAE@PAUTransition@cctz@time_internal@absl@@@Z
+    ??0?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@QAE@PAUTransitionType@cctz@time_internal@absl@@@Z
     ??0?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@QAE@XZ
     ??0?$optional@VCord@absl@@@absl@@QAE@Unullopt_t@1@@Z
     ??0?$optional_data@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@optional_internal@absl@@IAE@XZ
@@ -915,6 +943,8 @@
     ??0Refcount@cord_internal@absl@@QAE@XZ
     ??0Rep@GraphCycles@synchronization_internal@absl@@QAE@XZ
     ??0SchedulingHelper@base_internal@absl@@QAE@W4SchedulingMode@12@@Z
+    ??0ScopedDisable@SchedulingGuard@base_internal@absl@@QAE@XZ
+    ??0ScopedEnable@SchedulingGuard@base_internal@absl@@QAE@XZ
     ??0SpinLock@base_internal@absl@@QAE@W4SchedulingMode@12@@Z
     ??0SpinLockHolder@base_internal@absl@@QAE@PAVSpinLock@12@@Z
     ??0Status@absl@@QAE@W4StatusCode@1@Vstring_view@1@@Z
@@ -1000,6 +1030,7 @@
     ??1?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE@XZ
     ??1?$__split_buffer@UViableSubstitution@strings_internal@absl@@AAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QAE@XZ
     ??1?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE@XZ
+    ??1?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE@XZ
     ??1?$__vector_base@PAUCordRep@cord_internal@absl@@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@IAE@XZ
     ??1?$__vector_base@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@IAE@XZ
     ??1?$__vector_base@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@IAE@XZ
@@ -1048,6 +1079,8 @@
     ??1Refcount@cord_internal@absl@@QAE@XZ
     ??1Rep@GraphCycles@synchronization_internal@absl@@QAE@XZ
     ??1SchedulingHelper@base_internal@absl@@QAE@XZ
+    ??1ScopedDisable@SchedulingGuard@base_internal@absl@@QAE@XZ
+    ??1ScopedEnable@SchedulingGuard@base_internal@absl@@QAE@XZ
     ??1SpinLockHolder@base_internal@absl@@QAE@XZ
     ??1StatusRep@status_internal@absl@@QAE@XZ
     ??1Storage@?$FixedArray@PAUCordRep@cord_internal@absl@@$0PPPPPPPP@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QAE@XZ
@@ -1174,6 +1207,7 @@
     ??D?$move_iterator@PAUPayload@status_internal@absl@@@__1@std@@QBE$$QAUPayload@status_internal@absl@@XZ
     ??D?$move_iterator@PAUSubRange@absl@@@__1@std@@QBE$$QAUSubRange@absl@@XZ
     ??D?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@QBE$$QAUTransition@cctz@time_internal@absl@@XZ
+    ??D?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@QBE$$QAUTransitionType@cctz@time_internal@absl@@XZ
     ??D?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@QGAEAAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@XZ
     ??D?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QBEAAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@XZ
     ??DChunkIterator@Cord@absl@@QBE?AVstring_view@2@XZ
@@ -1188,6 +1222,7 @@
     ??E?$move_iterator@PAUPayload@status_internal@absl@@@__1@std@@QAEAAV012@XZ
     ??E?$move_iterator@PAUSubRange@absl@@@__1@std@@QAEAAV012@XZ
     ??E?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@QAEAAV012@XZ
+    ??E?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@QAEAAV012@XZ
     ??EChunkIterator@Cord@absl@@QAEAAV012@XZ
     ??Euint128@absl@@QAEAAV01@XZ
     ??Gabsl@@YA?AVDuration@0@V10@0@Z
@@ -1399,7 +1434,6 @@
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QBE_NXZ
     ?CheckLengthInternal@string_view@absl@@CAII@Z
     ?CheckNode@CordForest@absl@@CAXPAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@ABEXABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@ABUTransitionType@234@H_N0@Z
     ?Chunks@Cord@absl@@QBE?AVChunkRange@12@XZ
     ?CityHash32@hash_internal@absl@@YAIPBDI@Z
     ?CityHash64@hash_internal@absl@@YA_KPBDI@Z
@@ -1521,7 +1555,7 @@
     ?ErasePayload@Status@absl@@QAE_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QBE_NXZ
     ?Excess@str_format_internal@absl@@YAIII@Z
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AAEXABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@ABUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AAE_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPBDH@Z
@@ -1712,6 +1746,7 @@
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetTagForChar@str_format_internal@absl@@YA?AVConvTag@12@D@Z
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AAE_NH_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PAE@Z
     ?GetWaiter@Waiter@synchronization_internal@absl@@SAPAV123@PAUThreadIdentity@base_internal@3@@Z
     ?GetWeekday@absl@@YA?AW4weekday@detail@cctz@time_internal@1@V?$civil_time@Usecond_tag@time_internal@absl@@@3451@@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QBEIH@Z
@@ -1785,7 +1820,7 @@
     ?Load@?$AtomicHook@P6A?AV?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@absl@@Vstring_view@2@ABVCord@2@@Z@base_internal@absl@@QBEP6A?AV?$optional@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@3@Vstring_view@3@ABVCord@3@@ZXZ
     ?Load@?$AtomicHook@P6A_NW4LogSeverity@absl@@PBDHPAPADPAH@Z@base_internal@absl@@QBEP6A_NW4LogSeverity@3@PBDHPAPADPAH@ZXZ
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AAE_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AAE_NPAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QAE_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@ABE?AUabsolute_lookup@time_zone@234@_JABUTransition@234@@Z
@@ -1838,6 +1873,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QAEXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AAEXHPBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AAEXHPBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?Name@Impl@time_zone@cctz@time_internal@absl@@QBEABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@XZ
     ?Nanoseconds@absl@@YA?AVDuration@1@_J@Z
     ?NegateAndSubtractOne@time_internal@absl@@YA_J_J@Z
@@ -2205,6 +2241,7 @@
     ?ZeroDuration@absl@@YA?AVDuration@1@XZ
     ?__add_back_capacity@?$deque@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXXZ
     ?__addr@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEPAUTransition@cctz@time_internal@absl@@XZ
+    ?__addr@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEPAUTransitionType@cctz@time_internal@absl@@XZ
     ?__alloc@?$__bucket_list_deallocator@V?$allocator@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@__1@std@@@__1@std@@QAEAAV?$allocator@PAU?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@23@XZ
     ?__alloc@?$__deque_base@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@IAEAAV?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ
     ?__alloc@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@AAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEAAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@23@XZ
@@ -2403,6 +2440,7 @@
     ?__max_size@?$allocator_traits@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@CAIU?$integral_constant@_N$00@23@ABV?$allocator@UViableSubstitution@strings_internal@absl@@@23@@Z
     ?__max_size@?$allocator_traits@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@CAIU?$integral_constant@_N$00@23@ABV?$allocator@VFormatArgImpl@str_format_internal@absl@@@23@@Z
     ?__move_range@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXPAUTransition@cctz@time_internal@absl@@00@Z
+    ?__move_range@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXPAUTransitionType@cctz@time_internal@absl@@00@Z
     ?__node_alloc@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QAEAAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@23@XZ
     ?__ptr@?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@QAEPAU123@XZ
     ?__recommend@?$vector@PAUCordRep@cord_internal@absl@@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@ABEII@Z
@@ -2416,6 +2454,7 @@
     ?__swap_out_circular_buffer@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AAEXAAU?$__split_buffer@UConversionItem@ParsedFormatBase@str_format_internal@absl@@AAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEPAUTransition@cctz@time_internal@absl@@AAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXAAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEPAUTransitionType@cctz@time_internal@absl@@AAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PAU4567@@Z
     ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXAAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@@Z
     ?__swap_out_circular_buffer@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AAEXAAU?$__split_buffer@UViableSubstitution@strings_internal@absl@@AAV?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@23@@Z
     ?__upcast@?$__hash_node_base@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@QAEPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@23@XZ
@@ -2481,8 +2520,10 @@
     ?base@?$__wrap_iter@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@QBEPAUTransitionType@cctz@time_internal@absl@@XZ
     ?base@?$__wrap_iter@PBUConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@QBEPBUConversionItem@ParsedFormatBase@str_format_internal@absl@@XZ
     ?base@?$__wrap_iter@PBUTransition@cctz@time_internal@absl@@@__1@std@@QBEPBUTransition@cctz@time_internal@absl@@XZ
+    ?base@?$__wrap_iter@PBUTransitionType@cctz@time_internal@absl@@@__1@std@@QBEPBUTransitionType@cctz@time_internal@absl@@XZ
     ?base@?$move_iterator@PAPAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@QBEPAPAPBVImpl@time_zone@cctz@time_internal@absl@@XZ
     ?base@?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__1@std@@QBEPAUTransition@cctz@time_internal@absl@@XZ
+    ?base@?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__1@std@@QBEPAUTransitionType@cctz@time_internal@absl@@XZ
     ?begin@?$InlinedVector@PAUCordRep@cord_internal@absl@@$0CP@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@absl@@QAEPAPAUCordRep@cord_internal@2@XZ
     ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@QAEPAUPayload@status_internal@2@XZ
     ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@QBEPBUPayload@status_internal@2@XZ
@@ -2746,6 +2787,7 @@
     ?get@?$Storage@V?$allocator@UPayload@status_internal@absl@@@__1@std@@$0A@$00@internal_compressed_tuple@container_internal@absl@@QGBEABV?$allocator@UPayload@status_internal@absl@@@__1@std@@XZ
     ?get@?$Storage@V?$allocator@USubRange@absl@@@__1@std@@$0A@$00@internal_compressed_tuple@container_internal@absl@@QGAEAAV?$allocator@USubRange@absl@@@__1@std@@XZ
     ?get@?$__temp_value@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEAAUTransition@cctz@time_internal@absl@@XZ
+    ?get@?$__temp_value@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEAAUTransitionType@cctz@time_internal@absl@@XZ
     ?get@?$unique_ptr@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@QBEPAPBVImpl@time_zone@cctz@time_internal@absl@@XZ
     ?get@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@23@@__1@std@@QBEPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@23@XZ
     ?get@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QBEPAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@XZ
@@ -2874,6 +2916,7 @@
     ?push_back@?$deque@PBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXABQBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_back@?$vector@PAUCordRep@cord_internal@absl@@V?$allocator@PAUCordRep@cord_internal@absl@@@__1@std@@@__1@std@@QAEXABQAUCordRep@cord_internal@absl@@@Z
     ?push_back@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@QAEX$$QAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
+    ?push_back@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXABUTransition@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@AAV?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXABQAPBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?push_front@?$__split_buffer@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$allocator@PAPBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEX$$QAPAPBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?raw_code@Status@absl@@QBEHXZ
@@ -2891,6 +2934,7 @@
     ?rend@string_view@absl@@QBE?AV?$reverse_iterator@PBD@__1@std@@XZ
     ?replace_tree@InlineRep@Cord@absl@@QAEXPAUCordRep@cord_internal@3@@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXI@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXI@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QAEXI@Z
     ?reset@?$unique_ptr@$$CBVImpl@time_zone@cctz@time_internal@absl@@U?$default_delete@$$CBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXPBVImpl@time_zone@cctz@time_internal@absl@@@Z
     ?reset@?$unique_ptr@PAPBVImpl@time_zone@cctz@time_internal@absl@@V?$__allocator_destructor@V?$allocator@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@__1@std@@@__1@std@@QAEXPAPBVImpl@time_zone@cctz@time_internal@absl@@@Z
diff --git a/third_party/abseil-cpp/symbols_x86_rel.def b/third_party/abseil-cpp/symbols_x86_rel.def
index f3391ae..861f1ac 100644
--- a/third_party/abseil-cpp/symbols_x86_rel.def
+++ b/third_party/abseil-cpp/symbols_x86_rel.def
@@ -60,12 +60,15 @@
     ??$StrReplaceAll@V?$initializer_list@U?$pair@Vstring_view@absl@@V12@@__1@std@@@std@@@absl@@YAHABV?$initializer_list@U?$pair@Vstring_view@absl@@V12@@__1@std@@@std@@PAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@2@@Z
     ??$__emplace_back_slow_path@AAVstring_view@absl@@ABV12@AAI@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@AAEXAAVstring_view@absl@@ABV34@AAI@Z
     ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@ABUpiecewise_construct_t@23@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@_N@12@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@ABUpiecewise_construct_t@12@$$QAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@12@$$QAV?$tuple@$$V@12@@Z
+    ??$__push_back_slow_path@ABUTransition@cctz@time_internal@absl@@@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEXABUTransition@cctz@time_internal@absl@@@Z
     ??$__push_back_slow_path@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@?$vector@UConversionItem@ParsedFormatBase@str_format_internal@absl@@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__1@std@@@__1@std@@AAEX$$QAUConversionItem@ParsedFormatBase@str_format_internal@absl@@@Z
     ??$__upper_bound@AAUByCivilTime@Transition@cctz@time_internal@absl@@PBU2345@U2345@@__1@std@@YAPBUTransition@cctz@time_internal@absl@@PBU2345@0ABU2345@AAUByCivilTime@2345@@Z
     ??$assign@PBVFormatArgImpl@str_format_internal@absl@@@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@QAEXPBVFormatArgImpl@str_format_internal@absl@@0@Z
     ??$assign@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$optional_data_base@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@optional_internal@absl@@IAEX$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ??$emplace@$$V@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE?AV?$__wrap_iter@PAUTransition@cctz@time_internal@absl@@@12@V?$__wrap_iter@PBUTransition@cctz@time_internal@absl@@@12@@Z
+    ??$emplace@$$V@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAE?AV?$__wrap_iter@PAUTransitionType@cctz@time_internal@absl@@@12@V?$__wrap_iter@PBUTransitionType@cctz@time_internal@absl@@@12@@Z
     ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXXZ
+    ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXXZ
     ??$find@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QAE?AV?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@12@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@12@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QAE@Vstring_view@2@@Z
     ??0?$BigUnsigned@$03@strings_internal@absl@@QAE@XZ
@@ -226,7 +229,6 @@
     ?Ceil@absl@@YA?AVDuration@1@V21@0@Z
     ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QBE_NXZ
     ?CheckNode@CordForest@absl@@CAXPAUCordRep@cord_internal@2@@Z
-    ?CheckTransition@TimeZoneInfo@cctz@time_internal@absl@@ABEXABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@ABUTransitionType@234@H_N0@Z
     ?CityHash32@hash_internal@absl@@YAIPBDI@Z
     ?CityHash64@hash_internal@absl@@YA_KPBDI@Z
     ?CityHash64WithSeed@hash_internal@absl@@YA_KPBDI_K@Z
@@ -297,7 +299,7 @@
     ?Erase@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@inlined_vector_internal@absl@@QAEPAUPayload@status_internal@3@PBU453@0@Z
     ?ErasePayload@Status@absl@@QAE_NVstring_view@2@@Z
     ?Eval@Condition@absl@@QBE_NXZ
-    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AAEXABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@ABUHeader@1234@@Z
+    ?ExtendTransitions@TimeZoneInfo@cctz@time_internal@absl@@AAE_NXZ
     ?FDivDuration@absl@@YANVDuration@1@0@Z
     ?FailedPreconditionError@absl@@YA?AVStatus@1@Vstring_view@1@@Z
     ?FailureSignalToString@debugging_internal@absl@@YAPBDH@Z
@@ -381,6 +383,7 @@
     ?GetStride@ExponentialBiased@base_internal@absl@@QAE_J_J@Z
     ?GetTID@base_internal@absl@@YAIXZ
     ?GetThreadBlockedCounter@PerThreadSem@synchronization_internal@absl@@SAPAU?$atomic@H@__1@std@@XZ
+    ?GetTransitionType@TimeZoneInfo@cctz@time_internal@absl@@AAE_NH_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PAE@Z
     ?GetWord@?$BigUnsigned@$03@strings_internal@absl@@QBEIH@Z
     ?GetWord@?$BigUnsigned@$0FE@@strings_internal@absl@@QBEIH@Z
     ?Global@HashtablezSampler@container_internal@absl@@SAAAV123@XZ
@@ -423,7 +426,7 @@
     ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@W4LengthMod@12@@Z
     ?LengthToTag@CordTestAccess@strings_internal@absl@@SAEI@Z
     ?Load@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__1@std@@@__1@std@@ABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@67@@Z
-    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AAE_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PAVZoneInfoSource@234@@Z
+    ?Load@TimeZoneInfo@cctz@time_internal@absl@@AAE_NPAVZoneInfoSource@234@@Z
     ?Load@TimeZoneInfo@cctz@time_internal@absl@@QAE_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z
     ?LoadTimeZone@Impl@time_zone@cctz@time_internal@absl@@SA_NABV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PAV2345@@Z
     ?LocalTime@TimeZoneInfo@cctz@time_internal@absl@@ABE?AUabsolute_lookup@time_zone@234@_JABUTransition@234@@Z
@@ -455,6 +458,7 @@
     ?MultiplyByTenToTheNth@?$BigUnsigned@$0FE@@strings_internal@absl@@QAEXH@Z
     ?MultiplyStep@?$BigUnsigned@$03@strings_internal@absl@@AAEXHPBIHH@Z
     ?MultiplyStep@?$BigUnsigned@$0FE@@strings_internal@absl@@AAEXHPBIHH@Z
+    ?MutexDelay@synchronization_internal@absl@@YAHHH@Z
     ?NewArena@LowLevelAlloc@base_internal@absl@@SAPAUArena@123@H@Z
     ?NewExternalWithUninitializedReleaser@cord_internal@absl@@YA?AUExternalRepReleaserPair@12@Vstring_view@2@P6AIPAX0@ZI@Z
     ?NewRep@Status@absl@@CAIW4StatusCode@2@Vstring_view@2@V?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@@Z
@@ -695,6 +699,7 @@
     ?__invoke@<lambda_1>@?0???$NewExternalRep@UStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@absl@@QAE@$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@cord_internal@absl@@YAPAUCordRep@23@Vstring_view@3@$$QAUStringReleaser@?M@???$?0V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@$0A@@Cord@3@QAE@$$QAV?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@Z@@Z@CA?A?<auto>@@PAX0@Z
     ?__rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@AAEXI@Z
     ?__swap_out_circular_buffer@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEPAUTransition@cctz@time_internal@absl@@AAU?$__split_buffer@UTransition@cctz@time_internal@absl@@AAV?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@23@PAU4567@@Z
+    ?__swap_out_circular_buffer@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@AAEPAUTransitionType@cctz@time_internal@absl@@AAU?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@23@PAU4567@@Z
     ?__vallocate@?$vector@VFormatArgImpl@str_format_internal@absl@@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__1@std@@@__1@std@@AAEXI@Z
     ?clear@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QAEXXZ
     ?code@Status@absl@@QBE?AW4StatusCode@2@XZ
@@ -743,6 +748,7 @@
     ?raw_code@Status@absl@@QBEHXZ
     ?rehash@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@@23@@__1@std@@QAEXI@Z
     ?reserve@?$vector@UTransition@cctz@time_internal@absl@@V?$allocator@UTransition@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXI@Z
+    ?reserve@?$vector@UTransitionType@cctz@time_internal@absl@@V?$allocator@UTransitionType@cctz@time_internal@absl@@@__1@std@@@__1@std@@QAEXI@Z
     ?reserve@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__1@std@@@__1@std@@QAEXI@Z
     ?reset@?$unique_ptr@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@V?$__hash_node_destructor@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@__1@std@@@__1@std@@@23@@__1@std@@QAEXPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__1@std@@V?$allocator@D@23@@__1@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__1@std@@PAX@23@@Z
     ?reset@?$unique_ptr@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@U?$default_delete@V?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@__1@std@@@__1@std@@QAEXPAV?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__1@std@@@absl@@@Z
diff --git a/third_party/android_sdk/cipd/build-tools/30.0.1.yaml b/third_party/android_sdk/cipd/build-tools/30.0.1.yaml
new file mode 100644
index 0000000..09833e6
--- /dev/null
+++ b/third_party/android_sdk/cipd/build-tools/30.0.1.yaml
@@ -0,0 +1,13 @@
+# 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: chromium/third_party/android_sdk/public/build-tools/30.0.1
+description: build-tools Android SDK Build Tools
+root: ../../public/
+data:
+  - dir: build-tools/30.0.1
+# Some tools inspect their argv0 and don't handle CIPD's symlink structure
+# correctly. Install in copy mode so that they can find the other directories
+# relative to themselves.
+install_mode: copy
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index cb86fde..cb8de7ee 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -7,6 +7,26 @@
 import("//testing/test.gni")
 import("//third_party/blink/renderer/build/scripts/scripts.gni")
 
+blink_python_runner("make_generated_feature_policy_features") {
+  script = "../renderer/build/scripts/make_feature_policy_features.py"
+
+  inputs =
+      scripts_for_json5_files + [
+        "../renderer/build/scripts/make_feature_policy_features.py",
+        "../renderer/core/feature_policy/feature_policy_features.json5",
+        "../renderer/build/scripts/templates/feature_policy_features.cc.tmpl",
+      ]
+  outputs = [ "$root_gen_dir/third_party/blink/common/feature_policy/feature_policy_features.cc" ]
+
+  args = [
+    rebase_path("../renderer/core/feature_policy/feature_policy_features.json5",
+                root_build_dir),
+    "--output_dir",
+    rebase_path("$root_gen_dir/third_party/blink/common/feature_policy",
+                root_build_dir),
+  ]
+}
+
 blink_python_runner("make_generated_document_policy_features") {
   script = "../renderer/build/scripts/make_document_policy_features.py"
 
@@ -134,9 +154,11 @@
   ]
 
   sources += get_target_outputs(":make_generated_document_policy_features")
+  sources += get_target_outputs(":make_generated_feature_policy_features")
 
   public_deps = [
     ":make_generated_document_policy_features",
+    ":make_generated_feature_policy_features",
     "//third_party/blink/common/privacy_budget:privacy_budget",
     "//third_party/blink/public/common:headers",
   ]
diff --git a/third_party/blink/common/feature_policy/README.md b/third_party/blink/common/feature_policy/README.md
index dd3b064..abe4cb0 100644
--- a/third_party/blink/common/feature_policy/README.md
+++ b/third_party/blink/common/feature_policy/README.md
@@ -55,10 +55,6 @@
 2. Append the new feature enum with a brief description as well in
 `third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom`
 
-3. In `third_party/blink/renderer/platform/feature_policy/feature_policy.cc`,
-add an entry to `FeaturePolicy::GetDefaultFeatureList` with the default value
-to use for the new feature.
-
 ##### Integrate the feature behaviour with feature policy
 1. The most common way to check if features are enabled is `ExecutionContext::IsFeatureEnabled`.
 
diff --git a/third_party/blink/common/feature_policy/feature_policy.cc b/third_party/blink/common/feature_policy/feature_policy.cc
index dbb12f2..ec6cc93 100644
--- a/third_party/blink/common/feature_policy/feature_policy.cc
+++ b/third_party/blink/common/feature_policy/feature_policy.cc
@@ -9,6 +9,7 @@
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
+#include "third_party/blink/public/common/feature_policy/feature_policy_features.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
 
 namespace blink {
@@ -17,7 +18,7 @@
 // Extracts an Allowlist from a ParsedFeaturePolicyDeclaration.
 std::unique_ptr<FeaturePolicy::Allowlist> AllowlistFromDeclaration(
     const ParsedFeaturePolicyDeclaration& parsed_declaration,
-    const FeaturePolicy::FeatureList& feature_list) {
+    const FeaturePolicyFeatureList& feature_list) {
   std::unique_ptr<FeaturePolicy::Allowlist> result =
       base::WrapUnique(new FeaturePolicy::Allowlist());
   if (parsed_declaration.matches_all_origins)
@@ -106,15 +107,15 @@
     const ParsedFeaturePolicy& container_policy,
     const url::Origin& origin) {
   return CreateFromParentPolicy(parent_policy, container_policy, origin,
-                                GetDefaultFeatureList());
+                                GetFeaturePolicyFeatureList());
 }
 
 // static
 std::unique_ptr<FeaturePolicy> FeaturePolicy::CreateWithOpenerPolicy(
     const FeatureState& inherited_policies,
     const url::Origin& origin) {
-  std::unique_ptr<FeaturePolicy> new_policy =
-      base::WrapUnique(new FeaturePolicy(origin, GetDefaultFeatureList()));
+  std::unique_ptr<FeaturePolicy> new_policy = base::WrapUnique(
+      new FeaturePolicy(origin, GetFeaturePolicyFeatureList()));
   new_policy->inherited_policies_ = inherited_policies;
   new_policy->proposed_inherited_policies_ = inherited_policies;
   return new_policy;
@@ -144,10 +145,9 @@
   }
 
   // If no "allowlist" is specified, return default feature value.
-  const FeaturePolicy::FeatureDefault default_policy =
-      feature_list_.at(feature);
-  if (default_policy == FeaturePolicy::FeatureDefault::DisableForAll ||
-      (default_policy == FeaturePolicy::FeatureDefault::EnableForSelf &&
+  const FeaturePolicyFeatureDefault default_policy = feature_list_.at(feature);
+  if (default_policy == FeaturePolicyFeatureDefault::DisableForAll ||
+      (default_policy == FeaturePolicyFeatureDefault::EnableForSelf &&
        !origin_.IsSameOriginWith(origin)))
     return false;
   return inherited_value;
@@ -187,13 +187,12 @@
   if (allowlist != allowlists_.end())
     return FeaturePolicy::Allowlist(*(allowlist->second));
 
-  const FeaturePolicy::FeatureDefault default_policy =
-      feature_list_.at(feature);
+  const FeaturePolicyFeatureDefault default_policy = feature_list_.at(feature);
   FeaturePolicy::Allowlist default_allowlist;
 
-  if (default_policy == FeaturePolicy::FeatureDefault::EnableForAll) {
+  if (default_policy == FeaturePolicyFeatureDefault::EnableForAll) {
     default_allowlist.AddAll();
-  } else if (default_policy == FeaturePolicy::FeatureDefault::EnableForSelf) {
+  } else if (default_policy == FeaturePolicyFeatureDefault::EnableForSelf) {
     default_allowlist.Add(origin_);
   }
 
@@ -213,13 +212,13 @@
 
 FeaturePolicy::FeatureState FeaturePolicy::GetFeatureState() const {
   FeatureState feature_state;
-  for (const auto& pair : GetDefaultFeatureList())
+  for (const auto& pair : GetFeaturePolicyFeatureList())
     feature_state[pair.first] = GetFeatureValueForOrigin(pair.first, origin_);
   return feature_state;
 }
 
 FeaturePolicy::FeaturePolicy(url::Origin origin,
-                             const FeatureList& feature_list)
+                             const FeaturePolicyFeatureList& feature_list)
     : origin_(std::move(origin)), feature_list_(feature_list) {}
 
 FeaturePolicy::~FeaturePolicy() = default;
@@ -229,7 +228,7 @@
     const FeaturePolicy* parent_policy,
     const ParsedFeaturePolicy& container_policy,
     const url::Origin& origin,
-    const FeaturePolicy::FeatureList& features) {
+    const FeaturePolicyFeatureList& features) {
   // If there is a non-empty container policy, then there must also be a parent
   // policy.
   DCHECK(parent_policy || container_policy.empty());
@@ -260,7 +259,7 @@
       // For features which currently use 'self' default allowlist, set the
       // proposed inherited policy to "allow self" if the container policy does
       // not mention this feature at all.
-      if (feature.second == FeaturePolicy::FeatureDefault::EnableForSelf) {
+      if (feature.second == FeaturePolicyFeatureDefault::EnableForSelf) {
         bool found_in_container_policy = std::any_of(
             container_policy.begin(), container_policy.end(),
             [&](const auto& decl) { return decl.feature == feature.first; });
@@ -326,7 +325,7 @@
   }
 }
 
-const FeaturePolicy::FeatureList& FeaturePolicy::GetFeatureList() const {
+const FeaturePolicyFeatureList& FeaturePolicy::GetFeatureList() const {
   return feature_list_;
 }
 
@@ -373,131 +372,4 @@
   return mojom::FeaturePolicyFeature::kNotFound;
 }
 
-// static
-// See third_party/blink/public/common/feature_policy/feature_policy.h for
-// status of each feature (in spec, implemented, etc).
-const FeaturePolicy::FeatureList& FeaturePolicy::GetDefaultFeatureList() {
-  static base::NoDestructor<FeatureList> default_feature_list(
-      {{mojom::FeaturePolicyFeature::kAccelerometer,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kAmbientLightSensor,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kAutoplay,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintDPR,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintDeviceMemory,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintDownlink,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintECT,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintLang,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintRTT,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintUA,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kClientHintUAArch,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintUAPlatform,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintUAModel,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintUAMobile,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kClientHintUAFullVersion,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintUAPlatformVersion,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintViewportWidth,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClientHintWidth,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClipboardRead,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kClipboardWrite,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kCrossOriginIsolated,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kCamera,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kDocumentDomain,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kDocumentWrite,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kDownloads,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kEncryptedMedia,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kExecutionWhileOutOfViewport,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kExecutionWhileNotRendered,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kFocusWithoutUserActivation,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kFormSubmission,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       // kFrobulate is a test only feature.
-       {mojom::FeaturePolicyFeature::kFrobulate,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kFullscreen,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kGeolocation,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kGyroscope,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kHid,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kIdleDetection,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kMagnetometer,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kMicrophone,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kMidiFeature,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kModals,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kOrientationLock,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kPayment,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kPictureInPicture,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kPointerLock,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kPopups,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kPresentation,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kPublicKeyCredentialsGet,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kScript,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kSerial,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kSyncScript,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kSyncXHR,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kTopNavigation,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kUsb,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kVerticalScroll,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kScreenWakeLock,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kWebXr,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kStorageAccessAPI,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForAll)},
-       {mojom::FeaturePolicyFeature::kTrustTokenRedemption,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)},
-       {mojom::FeaturePolicyFeature::kConversionMeasurement,
-        FeatureDefault(FeaturePolicy::FeatureDefault::EnableForSelf)}});
-  return *default_feature_list;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/common/feature_policy/feature_policy_unittest.cc b/third_party/blink/common/feature_policy/feature_policy_unittest.cc
index 964f72a..e3a6aea2 100644
--- a/third_party/blink/common/feature_policy/feature_policy_unittest.cc
+++ b/third_party/blink/common/feature_policy/feature_policy_unittest.cc
@@ -36,14 +36,14 @@
  protected:
   FeaturePolicyTest()
       : feature_list_({{kDefaultOnFeature,
-                        FeaturePolicy::FeatureDefault(
-                            FeaturePolicy::FeatureDefault::EnableForAll)},
+                        FeaturePolicyFeatureDefault(
+                            FeaturePolicyFeatureDefault::EnableForAll)},
                        {kDefaultSelfFeature,
-                        FeaturePolicy::FeatureDefault(
-                            FeaturePolicy::FeatureDefault::EnableForSelf)},
+                        FeaturePolicyFeatureDefault(
+                            FeaturePolicyFeatureDefault::EnableForSelf)},
                        {kDefaultOffFeature,
-                        FeaturePolicy::FeatureDefault(
-                            FeaturePolicy::FeatureDefault::DisableForAll)}}) {}
+                        FeaturePolicyFeatureDefault(
+                            FeaturePolicyFeatureDefault::DisableForAll)}}) {}
 
   ~FeaturePolicyTest() override = default;
 
@@ -81,7 +81,7 @@
  private:
   // Contains the list of controlled features, so that we are guaranteed to
   // have at least one of each kind of default behaviour represented.
-  FeaturePolicy::FeatureList feature_list_;
+  FeaturePolicyFeatureList feature_list_;
 };
 
 TEST_F(FeaturePolicyTest, TestInitialPolicy) {
diff --git a/third_party/blink/common/messaging/web_message_port.cc b/third_party/blink/common/messaging/web_message_port.cc
index 744c314..5a8b0b32 100644
--- a/third_party/blink/common/messaging/web_message_port.cc
+++ b/third_party/blink/common/messaging/web_message_port.cc
@@ -40,8 +40,9 @@
 
 WebMessagePort::MessageReceiver::MessageReceiver() = default;
 WebMessagePort::MessageReceiver::~MessageReceiver() = default;
+
 bool WebMessagePort::MessageReceiver::OnMessage(Message) {
-  return true;
+  return false;
 }
 
 WebMessagePort::WebMessagePort() = default;
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index cc091a4..d8e150b3 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -283,7 +283,6 @@
     "web/modules/mediastream/media_stream_video_sink.h",
     "web/modules/mediastream/media_stream_video_source.h",
     "web/modules/mediastream/web_media_stream_device_observer.h",
-    "web/modules/mediastream/web_media_stream_renderer_factory.h",
     "web/modules/mediastream/web_media_stream_utils.h",
     "web/modules/mediastream/webmediaplayer_ms.h",
     "web/modules/service_worker/web_service_worker_context_client.h",
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index fcc0d24..1839fc3 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -76,6 +76,7 @@
     "feature_policy/document_policy.h",
     "feature_policy/document_policy_features.h",
     "feature_policy/feature_policy.h",
+    "feature_policy/feature_policy_features.h",
     "feature_policy/feature_policy_forward.h",
     "feature_policy/policy_value.h",
     "features.h",
diff --git a/third_party/blink/public/common/feature_policy/feature_policy.h b/third_party/blink/public/common/feature_policy/feature_policy.h
index 5ec85810..77a007b 100644
--- a/third_party/blink/public/common/feature_policy/feature_policy.h
+++ b/third_party/blink/public/common/feature_policy/feature_policy.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
 #include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/feature_policy/feature_policy_features.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-forward.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-forward.h"
 #include "url/origin.h"
@@ -69,9 +70,10 @@
 // feature is available when no policy has been declared, ans determines how the
 // feature is inherited across origin boundaries.
 //
-// If the default policy  is in effect for a frame, then it controls how the
+// If the default policy is in effect for a frame, then it controls how the
 // feature is inherited by any cross-origin iframes embedded by the frame. (See
-// the comments below in FeaturePolicy::FeatureDefault for specifics)
+// the comments in |FeaturePolicyFeatureDefault| in feature_policy_features.h
+// for specifics)
 //
 // Policy Inheritance
 // ------------------
@@ -80,7 +82,7 @@
 // receive the same set of enables features as the parent frame. Whether or not
 // features are inherited by cross-origin iframes without an explicit policy is
 // determined by the feature's default policy. (Again, see the comments in
-// FeaturePolicy::FeatureDefault for details)
+// |FeaturePolicyFeatureDefault| in feature_policy_features.h for details)
 
 // This struct holds feature policy allowlist data that needs to be replicated
 // between a RenderFrame and any of its associated RenderFrameProxies. A list of
@@ -164,30 +166,6 @@
     bool matches_opaque_src_{false};
   };
 
-  // The FeaturePolicy::FeatureDefault enum defines the default enable state for
-  // a feature when neither it nor any parent frame have declared an explicit
-  // policy. The three possibilities map directly to Feature Policy Allowlist
-  // semantics.
-  //
-  // The default values for each feature are set in GetDefaultFeatureList.
-  enum class FeatureDefault {
-    // Equivalent to []. If this default policy is in effect for a frame, then
-    // the feature will not be enabled for that frame or any of its children.
-    DisableForAll,
-
-    // Equivalent to ["self"]. If this default policy is in effect for a frame,
-    // then the feature will be enabled for that frame, and any same-origin
-    // child frames, but not for any cross-origin child frames.
-    EnableForSelf,
-
-    // Equivalent to ["*"]. If in effect for a frame, then the feature is
-    // enabled for that frame and all of its children.
-    EnableForAll
-  };
-
-  using FeatureList =
-      std::map<mojom::FeaturePolicyFeature, FeaturePolicy::FeatureDefault>;
-
   ~FeaturePolicy();
 
   static std::unique_ptr<FeaturePolicy> CreateFromParentPolicy(
@@ -228,8 +206,7 @@
   const url::Origin& GetOriginForTest() const { return origin_; }
 
   // Returns the list of features which can be controlled by Feature Policy.
-  const FeatureList& GetFeatureList() const;
-  static const FeatureList& GetDefaultFeatureList();
+  const FeaturePolicyFeatureList& GetFeatureList() const;
 
   static mojom::FeaturePolicyFeature FeatureForSandboxFlag(
       network::mojom::WebSandboxFlags flag);
@@ -237,12 +214,13 @@
  private:
   friend class FeaturePolicyTest;
 
-  FeaturePolicy(url::Origin origin, const FeatureList& feature_list);
+  FeaturePolicy(url::Origin origin,
+                const FeaturePolicyFeatureList& feature_list);
   static std::unique_ptr<FeaturePolicy> CreateFromParentPolicy(
       const FeaturePolicy* parent_policy,
       const ParsedFeaturePolicy& container_policy,
       const url::Origin& origin,
-      const FeatureList& features);
+      const FeaturePolicyFeatureList& features);
 
   // Updates the inherited policy with the declarations from the iframe allow*
   // attributes.
@@ -265,7 +243,7 @@
   // https://crbug.com/937131.
   FeatureState proposed_inherited_policies_;
 
-  const FeatureList& feature_list_;
+  const FeaturePolicyFeatureList& feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(FeaturePolicy);
 };
diff --git a/third_party/blink/public/common/feature_policy/feature_policy_features.h b/third_party/blink/public/common/feature_policy/feature_policy_features.h
new file mode 100644
index 0000000..3ea8794
--- /dev/null
+++ b/third_party/blink/public/common/feature_policy/feature_policy_features.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 THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_FEATURE_POLICY_FEATURES_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_FEATURE_POLICY_FEATURES_H_
+
+#include "base/containers/flat_map.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-forward.h"
+
+namespace blink {
+
+// The FeaturePolicyFeatureDefault enum defines the default enable state for
+// a feature when neither it nor any parent frame have declared an explicit
+// policy. The three possibilities map directly to Feature Policy Allowlist
+// semantics.
+//
+// The default values for each feature are set in GetDefaultFeatureList.
+enum class FeaturePolicyFeatureDefault {
+  // Equivalent to []. If this default policy is in effect for a frame, then
+  // the feature will not be enabled for that frame or any of its children.
+  DisableForAll,
+
+  // Equivalent to ["self"]. If this default policy is in effect for a frame,
+  // then the feature will be enabled for that frame, and any same-origin
+  // child frames, but not for any cross-origin child frames.
+  EnableForSelf,
+
+  // Equivalent to ["*"]. If in effect for a frame, then the feature is
+  // enabled for that frame and all of its children.
+  EnableForAll
+};
+
+using FeaturePolicyFeatureList =
+    std::map<mojom::FeaturePolicyFeature, FeaturePolicyFeatureDefault>;
+
+BLINK_COMMON_EXPORT const FeaturePolicyFeatureList&
+GetFeaturePolicyFeatureList();
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_FEATURE_POLICY_FEATURES_H_
diff --git a/third_party/blink/public/common/messaging/web_message_port.h b/third_party/blink/public/common/messaging/web_message_port.h
index 9e1daff..373ba20 100644
--- a/third_party/blink/public/common/messaging/web_message_port.h
+++ b/third_party/blink/public/common/messaging/web_message_port.h
@@ -217,9 +217,9 @@
   MessageReceiver& operator=(MessageReceiver&&) = delete;
   virtual ~MessageReceiver();
 
-  // Invoked by incoming messages. This should return true if the message was
-  // successfully handled, false otherwise. If this returns false the pipe
-  // will be torn down and a call to OnPipeError will be made.
+  // Called for each incoming |message|. Returns false if the message could not
+  // be successfully handled, in which case the pipe should be torn-down and
+  // OnPipeError() invoked.
   virtual bool OnMessage(Message message);
 
   // Invoked when the underlying pipe has experienced an error.
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 b182791..576af16c 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2682,6 +2682,8 @@
   kNativeFileSystemDragAndDrop = 3346,
   kRTCAdaptivePtime = 3347,
   kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest = 3348,
+  kNavigationTimingL2 = 3349,
+  kResourceTiming = 3350,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_string.h b/third_party/blink/public/platform/web_string.h
index 242819e..c8a5974 100644
--- a/third_party/blink/public/platform/web_string.h
+++ b/third_party/blink/public/platform/web_string.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STRING_H_
 
 #include <cstring>
+#include <limits>
 #include <string>
 
 #include "base/memory/scoped_refptr.h"
diff --git a/third_party/blink/public/web/modules/mediastream/web_media_stream_renderer_factory.h b/third_party/blink/public/web/modules/mediastream/web_media_stream_renderer_factory.h
deleted file mode 100644
index bfdf3e8..0000000
--- a/third_party/blink/public/web/modules/mediastream/web_media_stream_renderer_factory.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_WEB_MEDIA_STREAM_RENDERER_FACTORY_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_WEB_MEDIA_STREAM_RENDERER_FACTORY_H_
-
-#include "base/memory/ref_counted.h"
-#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_renderer.h"
-#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_video_renderer.h"
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}  // namespace base
-
-namespace blink {
-
-class WebMediaStream;
-class WebLocalFrame;
-
-// WebMediaStreamRendererFactory is used by WebMediaPlayerMS to create audio and
-// video feeds from a MediaStream provided an URL.
-// The factory methods are virtual in order for Blink web tests to be able to
-// override them.
-class BLINK_MODULES_EXPORT WebMediaStreamRendererFactory {
- public:
-  virtual ~WebMediaStreamRendererFactory() {}
-
-  // Returns a WebMediaStreamVideoRenderer that uses the given task runners.
-  // |io_task_runner| is used for passing video frames.
-  virtual scoped_refptr<WebMediaStreamVideoRenderer> GetVideoRenderer(
-      const WebMediaStream& web_stream,
-      const WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
-      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner) = 0;
-
-  virtual scoped_refptr<WebMediaStreamAudioRenderer> GetAudioRenderer(
-      const WebMediaStream& web_stream,
-      WebLocalFrame* web_frame,
-      const WebString& device_id,
-      base::RepeatingCallback<void()> on_render_error_callback) = 0;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_WEB_MEDIA_STREAM_RENDERER_FACTORY_H_
diff --git a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
index 9644479d..a8ca9685 100644
--- a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
+++ b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
@@ -51,7 +51,7 @@
 class WebMediaPlayerClient;
 class WebMediaStreamAudioRenderer;
 class WebMediaPlayerMSCompositor;
-class WebMediaStreamRendererFactory;
+class MediaStreamRendererFactory;
 class WebMediaStreamVideoRenderer;
 class WebString;
 class WebVideoFrameSubmitter;
@@ -277,7 +277,7 @@
   void SetGpuMemoryBufferVideoForTesting(
       media::GpuMemoryBufferVideoFramePool* gpu_memory_buffer_pool);
   void SetMediaStreamRendererFactoryForTesting(
-      std::unique_ptr<WebMediaStreamRendererFactory>);
+      std::unique_ptr<MediaStreamRendererFactory>);
 
   // Callback used to fulfill video.requestVideoFrameCallback() requests.
   void OnNewFramePresentedCallback();
@@ -334,7 +334,7 @@
 
   std::unique_ptr<media::MediaLog> media_log_;
 
-  std::unique_ptr<WebMediaStreamRendererFactory> renderer_factory_;
+  std::unique_ptr<MediaStreamRendererFactory> renderer_factory_;
 
   const scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner_;
   const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/third_party/blink/public/web/web_element.h b/third_party/blink/public/web/web_element.h
index c6544a3b..774692a1 100644
--- a/third_party/blink/public/web/web_element.h
+++ b/third_party/blink/public/web/web_element.h
@@ -33,14 +33,9 @@
 
 #include <vector>
 
-#include "base/optional.h"
 #include "third_party/blink/public/web/web_node.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
-namespace base {
-class UnguessableToken;
-}
-
 namespace gfx {
 class Size;
 }
@@ -120,11 +115,6 @@
   // /public/web interfaces.
   WebString GetComputedValue(const WebString& property_name);
 
-  // Returns the EmbeddingToken associated to this WebElement, or base::nullopt
-  // if there isn't one set. Currently, this can only return actual values for
-  // elements wrapping instances of an blink::HTMLFrameOwnerElement.
-  base::Optional<base::UnguessableToken> GetEmbeddingToken() const;
-
 #if INSIDE_BLINK
   WebElement(Element*);
   WebElement& operator=(Element*);
diff --git a/third_party/blink/renderer/build/scripts/make_feature_policy_features.py b/third_party/blink/renderer/build/scripts/make_feature_policy_features.py
new file mode 100644
index 0000000..a0005c0e
--- /dev/null
+++ b/third_party/blink/renderer/build/scripts/make_feature_policy_features.py
@@ -0,0 +1,35 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json5_generator
+import template_expander
+
+
+class FeaturePolicyFeatureWriter(json5_generator.Writer):
+    file_basename = 'feature_policy_features'
+
+    def __init__(self, json5_file_path, output_dir):
+        super(FeaturePolicyFeatureWriter,
+              self).__init__(json5_file_path, output_dir)
+
+        @template_expander.use_jinja('templates/' + self.file_basename +
+                                     '.cc.tmpl')
+        def generate_implementation():
+            return {
+                'header_guard':
+                self.make_header_guard(self._relative_output_dir +
+                                       self.file_basename + '.h'),
+                'input_files':
+                self._input_files,
+                'features':
+                self.json5_file.name_dictionaries
+            }
+
+        self._outputs = {
+            self.file_basename + '.cc': generate_implementation,
+        }
+
+
+if __name__ == '__main__':
+    json5_generator.Maker(FeaturePolicyFeatureWriter).main()
diff --git a/third_party/blink/renderer/build/scripts/templates/feature_policy_features.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/feature_policy_features.cc.tmpl
new file mode 100644
index 0000000..932aa9e
--- /dev/null
+++ b/third_party/blink/renderer/build/scripts/templates/feature_policy_features.cc.tmpl
@@ -0,0 +1,25 @@
+{% from 'templates/macros.tmpl' import license, source_files_for_generated_file %}
+{{license()}}
+
+{{ source_files_for_generated_file(template_file, input_files) }}
+
+#include "third_party/blink/public/common/feature_policy/feature_policy_features.h"
+
+#include "base/no_destructor.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
+
+namespace blink {
+
+const FeaturePolicyFeatureList& GetFeaturePolicyFeatureList() {
+  static const base::NoDestructor<FeaturePolicyFeatureList> feature_list({
+    {%- for feature in features %}
+      {
+        mojom::FeaturePolicyFeature::k{{feature.name}},
+        FeaturePolicyFeatureDefault::{{feature.feature_default}}
+      },
+    {%- endfor %}
+  });
+  return *feature_list;
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_environment.h b/third_party/blink/renderer/core/animation/css_interpolation_environment.h
index 7e15b15f..75764d5 100644
--- a/third_party/blink/renderer/core/animation/css_interpolation_environment.h
+++ b/third_party/blink/renderer/core/animation/css_interpolation_environment.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/animation/interpolation_environment.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -23,7 +24,9 @@
       : InterpolationEnvironment(map),
         state_(&state),
         style_(state.Style()),
-        variable_resolver_(variable_resolver) {}
+        variable_resolver_(variable_resolver) {
+    DCHECK(!RuntimeEnabledFeatures::CSSCascadeEnabled());
+  }
 
   explicit CSSInterpolationEnvironment(const InterpolationTypesMap& map,
                                        StyleResolverState& state,
@@ -33,7 +36,9 @@
         state_(&state),
         style_(state.Style()),
         cascade_(cascade),
-        cascade_resolver_(cascade_resolver) {}
+        cascade_resolver_(cascade_resolver) {
+    DCHECK(RuntimeEnabledFeatures::CSSCascadeEnabled());
+  }
 
   explicit CSSInterpolationEnvironment(const InterpolationTypesMap& map,
                                        const ComputedStyle& style)
diff --git a/third_party/blink/renderer/core/animation/transition_interpolation.cc b/third_party/blink/renderer/core/animation/transition_interpolation.cc
index ddbc082..5cea66c 100644
--- a/third_party/blink/renderer/core/animation/transition_interpolation.cc
+++ b/third_party/blink/renderer/core/animation/transition_interpolation.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/animation/interpolation_environment.h"
 #include "third_party/blink/renderer/core/animation/interpolation_type.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -48,9 +49,15 @@
 void TransitionInterpolation::Apply(StyleResolverState& state) const {
   CSSInterpolationTypesMap map(state.GetDocument().GetPropertyRegistry(),
                                state.GetDocument());
-  CSSInterpolationEnvironment environment(map, state, nullptr);
-  type_.Apply(CurrentInterpolableValue(), CurrentNonInterpolableValue(),
-              environment);
+  if (RuntimeEnabledFeatures::CSSCascadeEnabled()) {
+    CSSInterpolationEnvironment environment(map, state, nullptr, nullptr);
+    type_.Apply(CurrentInterpolableValue(), CurrentNonInterpolableValue(),
+                environment);
+  } else {
+    CSSInterpolationEnvironment environment(map, state, nullptr);
+    type_.Apply(CurrentInterpolableValue(), CurrentNonInterpolableValue(),
+                environment);
+  }
 }
 
 std::unique_ptr<TypedInterpolationValue>
diff --git a/third_party/blink/renderer/core/animation/transition_keyframe.cc b/third_party/blink/renderer/core/animation/transition_keyframe.cc
index f506cef..9360706 100644
--- a/third_party/blink/renderer/core/animation/transition_keyframe.cc
+++ b/third_party/blink/renderer/core/animation/transition_keyframe.cc
@@ -17,6 +17,7 @@
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -47,9 +48,16 @@
   StyleResolverState state(document, *element);
   state.SetStyle(ComputedStyle::Create());
   CSSInterpolationTypesMap map(document.GetPropertyRegistry(), document);
-  CSSInterpolationEnvironment environment(map, state, nullptr);
-  value_->GetType().Apply(value_->GetInterpolableValue(),
-                          value_->GetNonInterpolableValue(), environment);
+
+  if (RuntimeEnabledFeatures::CSSCascadeEnabled()) {
+    CSSInterpolationEnvironment environment(map, state, nullptr, nullptr);
+    value_->GetType().Apply(value_->GetInterpolableValue(),
+                            value_->GetNonInterpolableValue(), environment);
+  } else {
+    CSSInterpolationEnvironment environment(map, state, nullptr);
+    value_->GetType().Apply(value_->GetInterpolableValue(),
+                            value_->GetNonInterpolableValue(), environment);
+  }
 
   const ComputedStyle* style = state.Style();
   String property_value =
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 5921624..f3691be1 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -751,7 +751,7 @@
 }
 
 void Element::SetElementAttribute(const QualifiedName& name, Element* element) {
-  ExplicitlySetAttrElementsMap* explicitly_set_attr_elements_map_ =
+  ExplicitlySetAttrElementsMap* explicitly_set_attr_elements_map =
       GetDocument().GetExplicitlySetAttrElementsMap(this);
 
   // If the reflected element is explicitly null, or is not a member of this
@@ -762,7 +762,7 @@
   // https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:concept-shadow-including-ancestor
   if (!element ||
       !ElementIsDescendantOfShadowIncludingAncestor(*this, *element)) {
-    explicitly_set_attr_elements_map_->erase(name);
+    explicitly_set_attr_elements_map->erase(name);
     removeAttribute(name);
     return;
   }
@@ -782,7 +782,7 @@
   else
     setAttribute(name, id);
 
-  auto result = explicitly_set_attr_elements_map_->insert(name, nullptr);
+  auto result = explicitly_set_attr_elements_map->insert(name, nullptr);
   if (result.is_new_entry) {
     result.stored_value->value =
         MakeGarbageCollected<HeapVector<Member<Element>>>();
diff --git a/third_party/blink/renderer/core/editing/caret_display_item_client.cc b/third_party/blink/renderer/core/editing/caret_display_item_client.cc
index db64763..c717e19 100644
--- a/third_party/blink/renderer/core/editing/caret_display_item_client.cc
+++ b/third_party/blink/renderer/core/editing/caret_display_item_client.cc
@@ -258,7 +258,7 @@
   PhysicalRect drawing_rect = local_rect_;
   drawing_rect.Move(paint_offset);
 
-  DrawingRecorder recorder(context, *this, display_item_type);
+  DrawingRecorder recorder(context, *this, display_item_type, visual_rect_);
   IntRect paint_rect = PixelSnappedIntRect(drawing_rect);
   context.FillRect(paint_rect, color_, DarkModeFilter::ElementRole::kText);
 }
@@ -267,8 +267,4 @@
   return "Caret";
 }
 
-IntRect CaretDisplayItemClient::VisualRect() const {
-  return visual_rect_;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/caret_display_item_client.h b/third_party/blink/renderer/core/editing/caret_display_item_client.h
index c16bc36..ff55979 100644
--- a/third_party/blink/renderer/core/editing/caret_display_item_client.h
+++ b/third_party/blink/renderer/core/editing/caret_display_item_client.h
@@ -63,8 +63,7 @@
                   const PhysicalOffset& paint_offset,
                   DisplayItem::Type) const;
 
-  // DisplayItemClient methods.
-  IntRect VisualRect() const final;
+  // DisplayItemClient.
   String DebugName() const final;
 
  private:
diff --git a/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc b/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
index a89d234..e6a9abf 100644
--- a/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
+++ b/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
@@ -12,6 +12,8 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
 #include "third_party/blink/renderer/core/page/focus_controller.h"
 #include "third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -32,20 +34,20 @@
     return GetDocument().View()->GetFrame().Selection();
   }
 
-  const DisplayItemClient& GetCaretDisplayItemClient() const {
+  const CaretDisplayItemClient& GetCaretDisplayItemClient() const {
     return Selection().CaretDisplayItemClientForTesting();
   }
 
+  const IntRect& CaretVisualRect() const {
+    return GetCaretDisplayItemClient().visual_rect_;
+  }
+
   const LayoutBlock* CaretLayoutBlock() const {
-    return static_cast<const CaretDisplayItemClient&>(
-               GetCaretDisplayItemClient())
-        .layout_block_;
+    return GetCaretDisplayItemClient().layout_block_;
   }
 
   const LayoutBlock* PreviousCaretLayoutBlock() const {
-    return static_cast<const CaretDisplayItemClient&>(
-               GetCaretDisplayItemClient())
-        .previous_layout_block_;
+    return GetCaretDisplayItemClient().previous_layout_block_;
   }
 
   Text* AppendTextNode(const String& data) {
@@ -96,7 +98,7 @@
   EXPECT_TRUE(block->ShouldPaintCursorCaret());
   EXPECT_TRUE(GetCaretDisplayItemClient().IsValid());
 
-  auto caret_visual_rect = GetCaretDisplayItemClient().VisualRect();
+  auto caret_visual_rect = CaretVisualRect();
   EXPECT_EQ(1, caret_visual_rect.Width());
   EXPECT_EQ(block->Location(), LayoutPoint(caret_visual_rect.Location()));
 
@@ -121,7 +123,7 @@
   EXPECT_TRUE(block->ShouldPaintCursorCaret());
   EXPECT_TRUE(GetCaretDisplayItemClient().IsValid());
 
-  auto new_caret_visual_rect = GetCaretDisplayItemClient().VisualRect();
+  auto new_caret_visual_rect = CaretVisualRect();
   EXPECT_EQ(caret_visual_rect.Size(), new_caret_visual_rect.Size());
   EXPECT_EQ(caret_visual_rect.Y(), new_caret_visual_rect.Y());
   EXPECT_LT(caret_visual_rect.X(), new_caret_visual_rect.X());
@@ -150,7 +152,7 @@
   EXPECT_FALSE(block->ShouldPaintCursorCaret());
   // The caret display item client painted nothing, so is not validated.
   EXPECT_FALSE(GetCaretDisplayItemClient().IsValid());
-  EXPECT_EQ(IntRect(), GetCaretDisplayItemClient().VisualRect());
+  EXPECT_EQ(IntRect(), CaretVisualRect());
 
   EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
               UnorderedElementsAre(RasterInvalidationInfo{
@@ -179,7 +181,7 @@
   UpdateAllLifecyclePhasesForCaretTest();
   EXPECT_TRUE(GetCaretDisplayItemClient().IsValid());
 
-  auto caret_visual_rect1 = GetCaretDisplayItemClient().VisualRect();
+  auto caret_visual_rect1 = CaretVisualRect();
   EXPECT_EQ(1, caret_visual_rect1.Width());
   EXPECT_EQ(block1->FirstFragment().VisualRect().Location(),
             LayoutPoint(caret_visual_rect1.Location()));
@@ -201,7 +203,7 @@
   UpdateAllLifecyclePhasesForCaretTest();
   EXPECT_TRUE(GetCaretDisplayItemClient().IsValid());
 
-  auto caret_visual_rect2 = GetCaretDisplayItemClient().VisualRect();
+  auto caret_visual_rect2 = CaretVisualRect();
   EXPECT_EQ(1, caret_visual_rect2.Width());
   EXPECT_EQ(block2->FirstFragment().VisualRect().Location(),
             caret_visual_rect2.Location());
@@ -233,7 +235,7 @@
   UpdateAllLifecyclePhasesForCaretTest();
   EXPECT_TRUE(GetCaretDisplayItemClient().IsValid());
 
-  EXPECT_EQ(caret_visual_rect1, GetCaretDisplayItemClient().VisualRect());
+  EXPECT_EQ(caret_visual_rect1, CaretVisualRect());
   EXPECT_TRUE(block1->ShouldPaintCursorCaret());
   EXPECT_FALSE(block2->ShouldPaintCursorCaret());
 
@@ -324,7 +326,7 @@
   UpdateAllLifecyclePhasesForCaretTest();
   const auto* block = To<LayoutBlock>(GetDocument().body()->GetLayoutObject());
 
-  auto caret_visual_rect = GetCaretDisplayItemClient().VisualRect();
+  auto caret_visual_rect = CaretVisualRect();
   EXPECT_EQ(1, caret_visual_rect.Width());
   EXPECT_EQ(block->Location(), caret_visual_rect.Location());
 
@@ -345,7 +347,7 @@
   UpdateAllLifecyclePhasesForCaretTest();
   EXPECT_TRUE(GetCaretDisplayItemClient().IsValid());
 
-  auto new_caret_visual_rect = GetCaretDisplayItemClient().VisualRect();
+  auto new_caret_visual_rect = CaretVisualRect();
   EXPECT_EQ(caret_visual_rect.Size(), new_caret_visual_rect.Size());
   EXPECT_EQ(caret_visual_rect.Y(), new_caret_visual_rect.Y());
   EXPECT_LT(caret_visual_rect.X(), new_caret_visual_rect.X());
@@ -382,21 +384,17 @@
 
   EXPECT_TRUE(editor_block->ShouldPaintCursorCaret());
   EXPECT_EQ(editor_block, CaretLayoutBlock());
-  EXPECT_EQ(IntRect(116, 105, 1, 1), GetCaretDisplayItemClient().VisualRect());
+  EXPECT_EQ(IntRect(116, 105, 1, 1), CaretVisualRect());
 
   // Composite container.
   container->setAttribute(html_names::kStyleAttr, "will-change: transform");
   UpdateAllLifecyclePhasesForCaretTest();
-  // TODO(wangxianzhu): Why will-change:transform doens't trigger compositing
-  // in CAP?
-  if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
-    EXPECT_EQ(IntRect(50, 50, 1, 1), GetCaretDisplayItemClient().VisualRect());
-  }
+  EXPECT_EQ(IntRect(50, 50, 1, 1), CaretVisualRect());
 
   // Uncomposite container.
   container->setAttribute(html_names::kStyleAttr, "");
   UpdateAllLifecyclePhasesForCaretTest();
-  EXPECT_EQ(IntRect(116, 105, 1, 1), GetCaretDisplayItemClient().VisualRect());
+  EXPECT_EQ(IntRect(116, 105, 1, 1), CaretVisualRect());
 }
 
 class ParameterizedComputeCaretRectTest
@@ -413,6 +411,36 @@
   }
 };
 
+TEST_P(CaretDisplayItemClientTest, FullDocumentPaintingWithCaret) {
+  SetBodyInnerHTML(
+      "<div id='div' contentEditable='true' style='outline:none'>XYZ</div>");
+  GetDocument().GetPage()->GetFocusController().SetActive(true);
+  GetDocument().GetPage()->GetFocusController().SetFocused(true);
+  auto& div = *To<Element>(GetDocument().body()->firstChild());
+  auto& layout_text = *To<Text>(div.firstChild())->GetLayoutObject();
+  const DisplayItemClient* text_inline_box = layout_text.FirstTextBox();
+  if (layout_text.IsInLayoutNGInlineFormattingContext()) {
+    NGInlineCursor cursor;
+    cursor.MoveTo(layout_text);
+    text_inline_box = cursor.Current().GetDisplayItemClient();
+  }
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType),
+                          IsSameId(text_inline_box, kForegroundType)));
+
+  div.focus();
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(
+          IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+          IsSameId(text_inline_box, kForegroundType),
+          // New!
+          IsSameId(&GetCaretDisplayItemClient(), DisplayItem::kCaret)));
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          ParameterizedComputeCaretRectTest,
                          testing::Bool());
diff --git a/third_party/blink/renderer/core/editing/frame_caret.cc b/third_party/blink/renderer/core/editing/frame_caret.cc
index 09365ba..e60f733 100644
--- a/third_party/blink/renderer/core/editing/frame_caret.cc
+++ b/third_party/blink/renderer/core/editing/frame_caret.cc
@@ -66,10 +66,6 @@
   visitor->Trace(frame_);
 }
 
-const DisplayItemClient& FrameCaret::GetDisplayItemClient() const {
-  return *display_item_client_;
-}
-
 const PositionWithAffinity FrameCaret::CaretPosition() const {
   const VisibleSelection& selection =
       selection_editor_->ComputeVisibleSelectionInDOMTree();
diff --git a/third_party/blink/renderer/core/editing/frame_caret.h b/third_party/blink/renderer/core/editing/frame_caret.h
index a8f9162..1e54180 100644
--- a/third_party/blink/renderer/core/editing/frame_caret.h
+++ b/third_party/blink/renderer/core/editing/frame_caret.h
@@ -39,7 +39,6 @@
 namespace blink {
 
 class CaretDisplayItemClient;
-class DisplayItemClient;
 class FrameCaret;
 class GraphicsContext;
 class LayoutBlock;
@@ -55,7 +54,6 @@
   FrameCaret(LocalFrame&, const SelectionEditor&);
   ~FrameCaret();
 
-  const DisplayItemClient& GetDisplayItemClient() const;
   bool IsActive() const;
 
   void ScheduleVisualUpdateForPaintInvalidationIfNeeded();
@@ -82,8 +80,9 @@
   void PaintCaret(GraphicsContext&, const PhysicalOffset&) const;
 
   // For unit tests.
-  const DisplayItemClient& CaretDisplayItemClientForTesting() const;
-  const LayoutBlock* CaretLayoutBlockForTesting() const;
+  const CaretDisplayItemClient& CaretDisplayItemClientForTesting() const {
+    return *display_item_client_;
+  }
   bool ShouldPaintCaretForTesting() const { return should_paint_caret_; }
   void RecreateCaretBlinkTimerForTesting(
       scoped_refptr<base::SingleThreadTaskRunner>);
diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc
index 9476a45..29f6f57 100644
--- a/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -112,9 +112,9 @@
 
 FrameSelection::~FrameSelection() = default;
 
-const DisplayItemClient& FrameSelection::CaretDisplayItemClientForTesting()
+const CaretDisplayItemClient& FrameSelection::CaretDisplayItemClientForTesting()
     const {
-  return frame_caret_->GetDisplayItemClient();
+  return frame_caret_->CaretDisplayItemClientForTesting();
 }
 
 bool FrameSelection::IsAvailable() const {
diff --git a/third_party/blink/renderer/core/editing/frame_selection.h b/third_party/blink/renderer/core/editing/frame_selection.h
index 47d7ff9..6eae8384 100644
--- a/third_party/blink/renderer/core/editing/frame_selection.h
+++ b/third_party/blink/renderer/core/editing/frame_selection.h
@@ -42,7 +42,7 @@
 
 namespace blink {
 
-class DisplayItemClient;
+class CaretDisplayItemClient;
 class Element;
 class LayoutBlock;
 class LayoutText;
@@ -294,7 +294,7 @@
   friend class PaintControllerPaintTestBase;
   friend class SelectionControllerTest;
 
-  const DisplayItemClient& CaretDisplayItemClientForTesting() const;
+  const CaretDisplayItemClient& CaretDisplayItemClientForTesting() const;
 
   // Note: We have |selectionInFlatTree()| for unit tests, we should
   // use |visibleSelection<EditingInFlatTreeStrategy>()|.
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc
index eb8f3e7..1c0ed71 100644
--- a/third_party/blink/renderer/core/exported/web_element.cc
+++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -30,7 +30,6 @@
 
 #include "third_party/blink/public/web/web_element.h"
 
-#include "base/unguessable_token.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -41,7 +40,6 @@
 #include "third_party/blink/renderer/core/html/custom/v0_custom_element.h"
 #include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
 #include "third_party/blink/renderer/core/html/forms/text_control_element.h"
-#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/graphics/image.h"
@@ -202,13 +200,6 @@
   return computed_style->GetPropertyCSSValue(property_id)->CssText();
 }
 
-base::Optional<base::UnguessableToken> WebElement::GetEmbeddingToken() const {
-  if (auto* owner = DynamicTo<HTMLFrameOwnerElement>(ConstUnwrap<Element>()))
-    return owner->GetEmbeddingToken();
-
-  return base::nullopt;
-}
-
 WebElement::WebElement(Element* elem) : WebNode(elem) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebElement, IsElementNode())
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 b/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
index 87a6afde..ced3954 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
@@ -23,6 +23,14 @@
     // which gets parsed from the header or the allow attribute.
     feature_policy_name: {
     },
+
+    // feature_default: Default allowlist state for feature. This corresponds
+    // to enum class |FeaturePolicyFeatureDefault| in
+    // public/common/feature_policy/feature_policy_features.h
+    feature_default: {
+      default: "EnableForSelf",
+      valid_values: ["DisableForAll", "EnableForAll", "EnableForSelf"]
+    }
   },
 
   data: [
@@ -76,6 +84,7 @@
     {
       name: "ClientHintUA",
       feature_policy_name: "ch-ua",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForClientHints"],
     },
     {
@@ -96,6 +105,7 @@
     {
       name: "ClientHintUAMobile",
       feature_policy_name: "ch-ua-mobile",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForClientHints"],
     },
     {
@@ -139,15 +149,18 @@
     {
       name: "DocumentDomain",
       feature_policy_name: "document-domain",
+      feature_default: "EnableForAll",
     },
     {
       name: "DocumentWrite",
       feature_policy_name: "document-write",
+      feature_default: "EnableForAll",
       depends_on: ["ExperimentalProductivityFeatures"],
     },
     {
       name: "Downloads",
       feature_policy_name: "downloads",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
@@ -157,21 +170,25 @@
     {
       name: "ExecutionWhileOutOfViewport",
       feature_policy_name: "execution-while-out-of-viewport",
+      feature_default: "EnableForAll",
       depends_on: ["FreezeFramesOnVisibility"],
     },
     {
       name: "ExecutionWhileNotRendered",
       feature_policy_name: "execution-while-not-rendered",
+      feature_default: "EnableForAll",
       depends_on: ["FreezeFramesOnVisibility"],
     },
     {
       name: "FocusWithoutUserActivation",
       feature_policy_name: "focus-without-user-activation",
+      feature_default: "EnableForAll",
       depends_on: ["BlockingFocusWithoutUserActivation"],
     },
     {
       name: "FormSubmission",
       feature_policy_name: "forms",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
@@ -216,11 +233,13 @@
     {
       name: "Modals",
       feature_policy_name: "modals",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
       name: "OrientationLock",
       feature_policy_name: "orientation-lock",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
@@ -231,21 +250,25 @@
     {
       name: "PictureInPicture",
       feature_policy_name: "picture-in-picture",
+      feature_default: "EnableForAll",
       depends_on: ["PictureInPictureAPI"],
     },
     {
       name: "PointerLock",
       feature_policy_name: "pointer-lock",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
       name: "Popups",
       feature_policy_name: "popups",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
       name: "Presentation",
       feature_policy_name: "presentation",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
@@ -261,6 +284,7 @@
     {
       name: "Script",
       feature_policy_name: "scripts",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
@@ -270,21 +294,25 @@
     },
     {
       name: "StorageAccessAPI",
+      feature_default: "EnableForAll",
       feature_policy_name: "storage-access-api",
       depends_on: ["StorageAccessAPI"],
     },
     {
       name: "SyncScript",
       feature_policy_name: "sync-script",
+      feature_default: "EnableForAll",
       depends_on: ["ExperimentalProductivityFeatures"],
     },
     {
       name: "SyncXHR",
+      feature_default: "EnableForAll",
       feature_policy_name: "sync-xhr",
     },
     {
       name: "TopNavigation",
       feature_policy_name: "top-navigation",
+      feature_default: "EnableForAll",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
@@ -300,6 +328,7 @@
     {
       name: "VerticalScroll",
       feature_policy_name: "vertical-scroll",
+      feature_default: "EnableForAll",
       depends_on: ["ExperimentalProductivityFeatures"],
     },
     {
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc b/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
index 6542f68..4579d02a 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
@@ -438,6 +438,13 @@
 
 internal::FeaturePolicyNode ParsingContext::ParsePermissionsPolicyToIR(
     const String& policy) {
+  if (policy.length() > MAX_LENGTH_PARSE) {
+    logger_.Error("Permissions policy declaration exceeds size limit(" +
+                  String::Number(policy.length()) + ">" +
+                  String::Number(MAX_LENGTH_PARSE) + ")");
+    return {};
+  }
+
   auto root = net::structured_headers::ParseDictionary(policy.Utf8());
   if (!root) {
     logger_.Error(
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
index 9d97418..4dc0180 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
@@ -609,7 +609,14 @@
       policy_string.c_str(), origin_a_.get(), origin_b_.get(), logger,
       test_feature_name_map);
   EXPECT_EQ(1UL, logger.GetMessages().size())
-      << "Should fail to parse string with size " << policy_string.size();
+      << "Should fail to parse feature policy string with size "
+      << policy_string.size();
+  FeaturePolicyParser::ParsePermissionsPolicyForTest(
+      policy_string.c_str(), origin_a_.get(), origin_b_.get(), logger,
+      test_feature_name_map);
+  EXPECT_EQ(2UL, logger.GetMessages().size())
+      << "Should fail to parse permissions policy string with size "
+      << policy_string.size();
 }
 
 // Test histogram counting the use of feature policies in header.
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index ea9c45d..d0e5c20 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -248,6 +248,12 @@
       GetContentSecurityPolicyDelegate());
 }
 
+void LocalDOMWindow::Initialize() {
+  GetAgent()->AttachContext(this);
+  if (auto* agent_metrics = GetFrame()->GetPage()->GetAgentMetricsCollector())
+    agent_metrics->DidAttachWindow(*this);
+}
+
 void LocalDOMWindow::AcceptLanguagesChanged() {
   if (navigator_)
     navigator_->SetLanguagesDirty();
@@ -666,27 +672,13 @@
 
 Document* LocalDOMWindow::InstallNewDocument(const DocumentInit& init) {
   DCHECK_EQ(init.GetFrame(), GetFrame());
-  DCHECK(!document_ || !document_->IsActive());
-
-  bool is_first_document = !document_;
-
-  // Explicitly null document_ here so that it is always null when Document's
-  // constructor is running. This ensures that no code running from the
-  // constructor obeserves a situation where dom_window_->document() is a
-  // a different Document.
-  document_ = nullptr;
+  DCHECK(!document_);
   document_ = init.CreateDocument();
   document_->Initialize();
 
   if (!GetFrame())
     return document_;
 
-  if (is_first_document) {
-    GetAgent()->AttachContext(this);
-    if (auto* agent_metrics = GetFrame()->GetPage()->GetAgentMetricsCollector())
-      agent_metrics->DidAttachWindow(*this);
-  }
-
   GetFrame()->GetScriptController().UpdateDocument();
   document_->GetViewportData().UpdateViewportDescription();
   if (FrameScheduler* frame_scheduler = GetFrame()->GetFrameScheduler()) {
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 38f9684a..b62fa39 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -110,6 +110,9 @@
 
   LocalFrame* GetFrame() const { return To<LocalFrame>(DOMWindow::GetFrame()); }
 
+  void Initialize();
+  void ClearForReuse() { document_ = nullptr; }
+
   // Bind Content Security Policy to this window. This will cause the
   // CSP to resolve the 'self' attribute and all policies will then be
   // applied to this document.
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 8a85b12..535e84df 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -732,6 +732,7 @@
   }
   GetScriptController().ClearWindowProxy();
   dom_window_ = dom_window;
+  dom_window->Initialize();
 }
 
 Document* LocalFrame::GetDocument() const {
@@ -1823,6 +1824,7 @@
   // Any Document requires Shutdown() before detach, even the initial empty
   // document.
   GetDocument()->Shutdown();
+  DomWindow()->ClearForReuse();
 
   DomWindow()->InstallNewDocument(
       DocumentInit::Create()
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index 63c40273..1b9e856 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -547,6 +547,7 @@
     "ng/table/layout_ng_table_cell_legacy.h",
     "ng/table/layout_ng_table_column.cc",
     "ng/table/layout_ng_table_column.h",
+    "ng/table/layout_ng_table_column_visitor.h",
     "ng/table/layout_ng_table_interface.h",
     "ng/table/layout_ng_table_row.cc",
     "ng/table/layout_ng_table_row.h",
@@ -560,6 +561,8 @@
     "ng/table/ng_table_layout_algorithm_helpers.h",
     "ng/table/ng_table_layout_algorithm_types.cc",
     "ng/table/ng_table_layout_algorithm_types.h",
+    "ng/table/ng_table_layout_algorithm_utils.cc",
+    "ng/table/ng_table_layout_algorithm_utils.h",
     "order_iterator.cc",
     "order_iterator.h",
     "overflow_model.h",
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
index af75b0b..0cad220 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -33,7 +33,7 @@
   LayoutBlockFlow* GetLayoutBlockFlow() const {
     return To<LayoutBlockFlow>(box_);
   }
-  NGLayoutInputNode NextSibling() { return nullptr; }
+  NGLayoutInputNode NextSibling() const { return nullptr; }
 
   // True in quirks mode or limited-quirks mode, which require line-height
   // quirks.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
index 380dc1b5..b5d5d87 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
@@ -12,6 +12,9 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
@@ -60,6 +63,25 @@
 
 }  // namespace
 
+bool NGLayoutInputNode::IsEmptyTableSection() const {
+  return box_->IsTableSection() && To<LayoutNGTableSection>(box_)->IsEmpty();
+}
+
+wtf_size_t NGLayoutInputNode::TableColumnSpan() const {
+  DCHECK(IsTableCol() || IsTableColgroup());
+  return To<LayoutNGTableColumn>(box_)->Span();
+}
+
+wtf_size_t NGLayoutInputNode::TableCellColspan() const {
+  DCHECK(box_->IsTableCell());
+  return To<LayoutNGTableCell>(box_)->ColSpan();
+}
+
+wtf_size_t NGLayoutInputNode::TableCellRowspan() const {
+  DCHECK(box_->IsTableCell());
+  return To<LayoutNGTableCell>(box_)->ComputedRowSpan();
+}
+
 MinMaxSizesResult NGLayoutInputNode::ComputeMinMaxSizes(
     WritingMode writing_mode,
     const MinMaxSizesInput& input,
@@ -87,7 +109,7 @@
     *computed_block_size = LayoutUnit(legacy_sizing_info.size.Height());
 }
 
-NGLayoutInputNode NGLayoutInputNode::NextSibling() {
+NGLayoutInputNode NGLayoutInputNode::NextSibling() const {
   auto* inline_node = DynamicTo<NGInlineNode>(this);
   return inline_node ? inline_node->NextSibling()
                      : To<NGBlockNode>(*this).NextSibling();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
index 26ce67d..bbac3fa 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
@@ -143,6 +143,23 @@
 
   bool IsTableCaption() const { return IsBlock() && box_->IsTableCaption(); }
 
+  // Section with empty rows is considered empty.
+  bool IsEmptyTableSection() const;
+
+  bool IsTableCol() const {
+    return Style().Display() == EDisplay::kTableColumn;
+  }
+
+  bool IsTableColgroup() const {
+    return Style().Display() == EDisplay::kTableColumnGroup;
+  }
+
+  wtf_size_t TableColumnSpan() const;
+
+  wtf_size_t TableCellColspan() const;
+
+  wtf_size_t TableCellRowspan() const;
+
   bool IsMathRoot() const { return box_->IsMathMLRoot(); }
 
   bool IsAnonymousBlock() const { return box_->IsAnonymousBlock(); }
@@ -193,7 +210,7 @@
                      base::Optional<LayoutUnit>* computed_block_size) const;
 
   // Returns the next sibling.
-  NGLayoutInputNode NextSibling();
+  NGLayoutInputNode NextSibling() const;
 
   Document& GetDocument() const { return box_->GetDocument(); }
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
index c72d3fd..ae92132 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
@@ -48,7 +48,7 @@
 }
 
 void LayoutNGTableColumn::ClearNeedsLayoutForChildren() const {
-  LayoutObject* child = FirstChild();
+  LayoutObject* child = children_.FirstChild();
   while (child) {
     child->ClearNeedsLayout();
     child = child->NextSibling();
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
index 311a47c3..0db6305e 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
@@ -48,10 +48,6 @@
 
   void ImageChanged(WrappedImagePtr, CanDeferInvalidation) final;
 
-  LayoutObject* FirstChild() const { return children_.FirstChild(); }
-
-  void SlowFirstChild() const = delete;
-
  protected:
   // Required by LayoutBox, but not used.
   MinMaxSizes ComputeIntrinsicLogicalWidths() const override {
@@ -74,8 +70,13 @@
 
   LayoutObjectChildList* VirtualChildren() override { return &children_; }
 
+  const LayoutObjectChildList* VirtualChildren() const override {
+    return &children_;
+  }
+
   // LayoutObject methods end
 
+ private:
   unsigned span_ = 1;
   LayoutObjectChildList children_;
 };
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column_visitor.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column_visitor.h
new file mode 100644
index 0000000..538d97b
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column_visitor.h
@@ -0,0 +1,83 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_COLUMN_VISITOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_COLUMN_VISITOR_H_
+
+#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+
+namespace blink {
+
+// Rules for computed spans of COLGROUP/COL elements are complicated.
+// 1) Spans cannot protrude outside of table boundary.
+// 2) Colgroup span is
+//    a) sum of children COL spans if it has children.
+//    b) span attribute if it has no children.
+//
+// This function implements a Visitor pattern for LayoutNGTableColumn
+// traversal, and computes correct spans.
+//
+// class Visitor {
+//   void VisitCol(const NGBlockNode& column,
+//                 wtf_size_t start_column_index,
+//                 wtf_size_t span);
+//   void EnterColgroup(const NGBlockNode&  colgroup,
+//                      wtf_size_t start_column_index);
+//   void LeaveColgroup(const NGBlockNode& colgroup,
+//                      wtf_size_t start_column_index,
+//                      wtf_size_t span,
+//                      bool has_children);
+// }
+template <typename Visitor>
+void VisitLayoutNGTableColumn(const Vector<NGBlockNode>& columns,
+                              wtf_size_t table_column_count,
+                              Visitor* visitor) {
+  wtf_size_t current_column_index = 0;
+
+  auto VisitCol = [&](const NGBlockNode& col) {
+    wtf_size_t span = col.TableColumnSpan();
+    span = std::min(span, table_column_count - current_column_index);
+    visitor->VisitCol(col, current_column_index, span);
+    current_column_index += span;
+    return span;
+  };
+
+  for (const NGBlockNode& table_column : columns) {
+    // Col spans can cause columns to extend beyond table's edge.
+    // These columns are ignored.
+    if (current_column_index >= table_column_count)
+      break;
+    if (table_column.IsTableCol()) {  // COL element.
+      VisitCol(table_column);
+      continue;
+    }
+    DCHECK(table_column.IsTableColgroup());
+    // Visit COLGROUP element.
+    visitor->EnterColgroup(table_column, current_column_index);
+    NGBlockNode col_child = To<NGBlockNode>(table_column.FirstChild());
+    wtf_size_t colgroup_start_index = current_column_index;
+    wtf_size_t colgroup_span = 0;
+    bool has_children = bool(col_child);
+    if (col_child) {
+      while (col_child) {
+        colgroup_span += VisitCol(col_child);
+        if (current_column_index >= table_column_count)
+          break;
+        col_child = To<NGBlockNode>(col_child.NextSibling());
+      }
+    } else {
+      // If COLGROUP has no children, its span is defined by the COLGROUP.
+      colgroup_span = std::min(table_column.TableColumnSpan(),
+                               table_column_count - current_column_index);
+      current_column_index += colgroup_span;
+    }
+    visitor->LeaveColgroup(table_column, colgroup_start_index, colgroup_span,
+                           has_children);
+  }
+}
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_COLUMN_VISITOR_H_
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc
index 61c0ad3..00c99e3 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.cc
@@ -193,13 +193,12 @@
       cell_style);
 }
 
-NGBoxStrut NGTableBorders::CellPadding(wtf_size_t row,
-                                       wtf_size_t column,
-                                       const ComputedStyle& cell_style) const {
+// As we are determining the intrinsic size of the table at this stage,
+// %-padding resolves against an indefinite size.
+NGBoxStrut NGTableBorders::CellPaddingForMeasure(
+    const ComputedStyle& cell_style) const {
   if (!cell_style.MayHavePadding())
     return NGBoxStrut();
-  // TODO(atotic) Need to add PercentageResolutionSize to resolve padding
-  // correctly.
   return ComputePadding(
       NGConstraintSpaceBuilder(writing_direction_.GetWritingMode(),
                                writing_direction_.GetWritingMode(),
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h
index 1d55df6..4fdde32 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h
@@ -159,6 +159,10 @@
     return *cached_table_border_padding_;
   }
 
+  WritingDirectionMode TableWritingDirection() const {
+    return writing_direction_;
+  }
+
   // This method is necessary because collapsed table's border rect and
   // visual overflow rect use different borders.
   // Border rect uses inline start/end of the first row.
@@ -176,20 +180,7 @@
                         wtf_size_t section_index,
                         const ComputedStyle& cell_style) const;
 
-  NGBoxStrut CellPadding(wtf_size_t row,
-                         wtf_size_t column,
-                         const ComputedStyle& cell_style) const;
-
-  NGBoxStrut CellBorderPadding(wtf_size_t row,
-                               wtf_size_t column,
-                               wtf_size_t rowspan,
-                               wtf_size_t colspan,
-                               wtf_size_t section_index,
-                               const ComputedStyle& cell_style) const {
-    return CellBorder(row, column, rowspan, colspan, section_index,
-                      cell_style) +
-           CellPadding(row, column, cell_style);
-  }
+  NGBoxStrut CellPaddingForMeasure(const ComputedStyle& cell_style) const;
 
   void ComputeCollapsedTableBorderPadding(wtf_size_t table_row_count,
                                           wtf_size_t table_column_count);
@@ -348,4 +339,7 @@
 };
 
 }  // namespace blink
+
+WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::NGTableBorders::Edge)
+
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_NG_TABLE_BORDERS_H_
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
new file mode 100644
index 0000000..b85cfb5b
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
@@ -0,0 +1,435 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h"
+
+#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column_visitor.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
+#include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
+#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.h"
+
+namespace blink {
+
+namespace {
+
+NGTableTypes::Row ComputeMinimumRowBlockSize(
+    const NGBlockNode& row,
+    const LayoutUnit cell_percentage_inline_size,
+    const bool is_restricted_block_size_table,
+    const NGTableTypes::ColumnLocations& column_locations,
+    const NGTableBorders& table_borders,
+    wtf_size_t row_index,
+    wtf_size_t section_index,
+    bool is_section_collapsed,
+    NGTableTypes::CellBlockConstraints* cell_block_constraints,
+    NGTableTypes::RowspanCells* rowspan_cells,
+    NGColspanCellTabulator* colspan_cell_tabulator) {
+  const WritingMode table_writing_mode =
+      table_borders.TableWritingDirection().GetWritingMode();
+
+  auto CreateCellConstraintSpace = [&column_locations, &table_writing_mode,
+                                    &is_restricted_block_size_table,
+                                    &cell_percentage_inline_size](
+                                       const NGBlockNode& cell,
+                                       wtf_size_t start_column_index,
+                                       const NGBoxStrut& cell_borders) {
+    wtf_size_t start_column = start_column_index;
+    wtf_size_t end_column = std::min(start_column + cell.TableCellColspan() - 1,
+                                     column_locations.size() - 1);
+    LayoutUnit cell_inline_size = column_locations[end_column].offset +
+                                  column_locations[end_column].size -
+                                  column_locations[start_column].offset;
+    // TODO(crbug.com/736072): Support orthogonal table cells.
+    // See http://wpt.live/css/css-writing-modes/table-cell-001.html
+    NGConstraintSpaceBuilder builder(table_writing_mode,
+                                     cell.Style().GetWritingMode(),
+                                     /* is_new_fc */ true);
+    DCHECK_EQ(table_writing_mode, cell.Style().GetWritingMode());
+    builder.SetTextDirection(cell.Style().Direction());
+    builder.SetTableCellBorders(cell_borders);
+    builder.SetAvailableSize(LogicalSize(cell_inline_size, kIndefiniteSize));
+    // Standard:
+    // https://www.w3.org/TR/css-tables-3/#computing-the-table-height "the
+    // computed height (if definite, percentages being considered 0px)"
+    LogicalSize percentage_resolution_size(cell_percentage_inline_size,
+                                           kIndefiniteSize);
+    builder.SetPercentageResolutionSize(percentage_resolution_size);
+    builder.SetReplacedPercentageResolutionSize(percentage_resolution_size);
+    builder.SetIsFixedInlineSize(true);
+    builder.SetIsTableCell(true);
+    builder.SetIsRestrictedBlockSizeTableCell(is_restricted_block_size_table);
+    builder.SetNeedsBaseline(true);
+    builder.SetCacheSlot(NGCacheSlot::kMeasure);
+    return builder.ToConstraintSpace();
+  };
+
+  base::Optional<LayoutUnit> max_baseline;
+  LayoutUnit max_descent;
+  LayoutUnit row_block_size;
+  base::Optional<float> row_percent;
+  bool is_constrained = false;
+  bool baseline_depends_on_percentage_block_size_descendant = false;
+  bool has_rowspan_start = false;
+  wtf_size_t start_cell_index = cell_block_constraints->size();
+
+  // Gather block sizes of all cells.
+  for (NGBlockNode cell = To<NGBlockNode>(row.FirstChild()); cell;
+       cell = To<NGBlockNode>(cell.NextSibling())) {
+    colspan_cell_tabulator->FindNextFreeColumn();
+    const ComputedStyle& cell_style = cell.Style();
+    const NGBoxStrut cell_borders = table_borders.CellBorder(
+        row_index, colspan_cell_tabulator->CurrentColumn(),
+        cell.TableCellRowspan(), cell.TableCellColspan(), section_index,
+        cell_style);
+    const NGConstraintSpace cell_constraint_space = CreateCellConstraintSpace(
+        cell, colspan_cell_tabulator->CurrentColumn(), cell_borders);
+    scoped_refptr<const NGLayoutResult> layout_result =
+        cell.Layout(cell_constraint_space);
+    const NGBoxFragment fragment(
+        table_writing_mode, table_borders.TableWritingDirection().Direction(),
+        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment()));
+
+    LayoutUnit baseline;
+    // https://www.w3.org/TR/css-tables-3/#row-layout "If there is no such
+    // line box or table-row, the baseline is the bottom of content edge of
+    // the cell box."
+    // Only baseline-aligned cells contribute to row baseline.
+    if (NGTableAlgorithmUtils::IsBaseline(cell_style.VerticalAlign())) {
+      if (layout_result->HasDescendantThatDependsOnPercentageBlockSize())
+        baseline_depends_on_percentage_block_size_descendant = true;
+      baseline = NGTableAlgorithmUtils::CellBaselineFromFragment(fragment);
+      max_baseline = std::max(max_baseline.value_or(LayoutUnit()), baseline);
+    }
+
+    const wtf_size_t rowspan = cell.TableCellRowspan();
+    NGTableTypes::CellBlockConstraint cell_block_constraint =
+        NGTableTypes::CreateCellBlockConstraint(
+            cell, fragment.BlockSize(), baseline, cell_borders, row_index,
+            colspan_cell_tabulator->CurrentColumn(), rowspan);
+    colspan_cell_tabulator->ProcessCell(cell);
+    cell_block_constraints->push_back(cell_block_constraint);
+    is_constrained |= cell_block_constraint.is_constrained && rowspan == 1;
+
+    // Compute cell's css block size.
+    base::Optional<LayoutUnit> cell_css_block_size;
+    base::Optional<float> cell_css_percent;
+    const Length& cell_specified_block_length = cell_style.LogicalHeight();
+
+    // TODO(1105272) Handle cell_specified_block_length.IsCalculated()
+    if (cell_specified_block_length.IsPercent()) {
+      cell_css_percent = cell_specified_block_length.Percent();
+    } else if (cell_specified_block_length.IsFixed()) {
+      // NOTE: Ignore min/max-height for determining the |cell_css_block_size|.
+      NGBoxStrut cell_padding =
+          ComputePadding(cell_constraint_space, cell_style);
+      NGBoxStrut border_padding = cell_borders + cell_padding;
+      // https://quirks.spec.whatwg.org/#the-table-cell-height-box-sizing-quirk
+      if (cell.GetDocument().InQuirksMode() ||
+          cell_style.BoxSizing() == EBoxSizing::kBorderBox) {
+        cell_css_block_size =
+            std::max(border_padding.BlockSum(),
+                     LayoutUnit(cell_specified_block_length.Value()));
+      } else {
+        cell_css_block_size = border_padding.BlockSum() +
+                              LayoutUnit(cell_specified_block_length.Value());
+      }
+    }
+
+    if (rowspan == 1) {
+      if (cell_css_block_size || cell_css_percent)
+        is_constrained = true;
+      if (cell_css_percent)
+        row_percent = std::max(row_percent.value_or(0), *cell_css_percent);
+      // Cell's block layout ignores CSS block size properties. Row must use it
+      // to compute it's minimum block size.
+      if (cell_css_block_size)
+        row_block_size = std::max(row_block_size, *cell_css_block_size);
+      if (NGTableAlgorithmUtils::IsBaseline(
+              cell_block_constraint.vertical_align)) {
+        max_descent = std::max(max_descent,
+                               cell_block_constraint.min_block_size - baseline);
+        row_block_size = std::max(
+            row_block_size, max_baseline.value_or(LayoutUnit()) + max_descent);
+      } else {
+        row_block_size =
+            std::max(row_block_size, cell_block_constraint.min_block_size);
+      }
+    } else {
+      has_rowspan_start = true;
+      rowspan_cells->push_back(NGTableTypes::CreateRowspanCell(
+          row_index, rowspan, &cell_block_constraint, cell_css_block_size));
+    }
+  }
+  // Apply row's CSS block size.
+  const Length& row_specified_block_length = row.Style().LogicalHeight();
+  if (row_specified_block_length.IsPercent()) {
+    is_constrained = true;
+    row_percent =
+        std::max(row_percent.value_or(0), row_specified_block_length.Percent());
+  } else if (row_specified_block_length.IsFixed()) {
+    is_constrained = true;
+    row_block_size = std::max(LayoutUnit(row_specified_block_length.Value()),
+                              row_block_size);
+  }
+
+  return NGTableTypes::Row{
+      row_block_size,
+      max_baseline.value_or(row_block_size),
+      row_percent,
+      start_cell_index,
+      cell_block_constraints->size() - start_cell_index,
+      is_constrained,
+      baseline_depends_on_percentage_block_size_descendant,
+      has_rowspan_start,
+      /* is_collapsed */ is_section_collapsed ||
+          row.Style().Visibility() == EVisibility::kCollapse};
+}
+
+// Computes inline constraints for COLGROUP/COLs.
+class ColumnConstraintsBuilder {
+ public:
+  void VisitCol(const NGLayoutInputNode& column,
+                wtf_size_t start_column_index,
+                wtf_size_t span) {
+    // COL creates SPAN constraints. Its width is col css width, or enclosing
+    // colgroup css width.
+    NGTableTypes::Column col_constraint = NGTableTypes::CreateColumn(
+        column.Style(), !is_fixed_layout_ && colgroup_constraint_
+                            ? colgroup_constraint_->max_inline_size
+                            : base::nullopt);
+    for (wtf_size_t i = 0; i < span; ++i)
+      column_constraints_->push_back(col_constraint);
+    column.GetLayoutBox()->ClearNeedsLayout();
+  }
+
+  void EnterColgroup(const NGLayoutInputNode& colgroup,
+                     wtf_size_t start_column_index) {
+    colgroup_constraint_ =
+        NGTableTypes::CreateColumn(colgroup.Style(), base::nullopt);
+  }
+
+  void LeaveColgroup(const NGLayoutInputNode& colgroup,
+                     wtf_size_t start_column_index,
+                     wtf_size_t span,
+                     bool has_children) {
+    if (!has_children) {
+      for (wtf_size_t i = 0; i < span; ++i)
+        column_constraints_->push_back(*colgroup_constraint_);
+    }
+    colgroup_constraint_.reset();
+    colgroup.GetLayoutBox()->ClearNeedsLayout();
+    To<LayoutNGTableColumn>(colgroup.GetLayoutBox())
+        ->ClearNeedsLayoutForChildren();
+  }
+
+  ColumnConstraintsBuilder(NGTableTypes::Columns* column_constraints,
+                           bool is_fixed_layout)
+      : column_constraints_(column_constraints),
+        is_fixed_layout_(is_fixed_layout) {}
+
+ private:
+  NGTableTypes::Columns* column_constraints_;
+  bool is_fixed_layout_;
+  base::Optional<NGTableTypes::Column> colgroup_constraint_;
+};
+
+}  // namespace
+
+LayoutUnit NGTableAlgorithmUtils::CellBaselineFromFragment(
+    const NGBoxFragment& fragment) {
+  return fragment.FirstBaseline().value_or(fragment.BlockSize());
+}
+
+void NGTableAlgorithmUtils::ComputeColumnInlineConstraints(
+    const Vector<NGBlockNode>& columns,
+    bool is_fixed_layout,
+    NGTableTypes::Columns* column_constraints) {
+  ColumnConstraintsBuilder constraints_builder(column_constraints,
+                                               is_fixed_layout);
+  // |table_column_count| is UINT_MAX because columns will get trimmed later.
+  VisitLayoutNGTableColumn(columns, UINT_MAX, &constraints_builder);
+}
+
+void NGTableAlgorithmUtils::ComputeSectionInlineConstraints(
+    const NGBlockNode& section,
+    bool is_fixed_layout,
+    bool is_first_section,
+    WritingMode table_writing_mode,
+    const NGTableBorders& table_borders,
+    wtf_size_t section_index,
+    wtf_size_t* row_index,
+    NGTableTypes::CellInlineConstraints* cell_inline_constraints,
+    NGTableTypes::ColspanCells* colspan_cell_inline_constraints) {
+  NGColspanCellTabulator colspan_cell_tabulator;
+  bool is_first_row = true;
+  for (NGBlockNode row = To<NGBlockNode>(section.FirstChild()); row;
+       row = To<NGBlockNode>(row.NextSibling())) {
+    colspan_cell_tabulator.StartRow();
+
+    // Gather constraints for each cell, and merge them into
+    // CellInlineConstraints.
+    for (NGBlockNode cell = To<NGBlockNode>(row.FirstChild()); cell;
+         cell = To<NGBlockNode>(cell.NextSibling())) {
+      colspan_cell_tabulator.FindNextFreeColumn();
+      wtf_size_t colspan = cell.TableCellColspan();
+
+      bool ignore_because_of_fixed_layout =
+          is_fixed_layout && (!is_first_section || !is_first_row);
+
+      wtf_size_t max_column = NGTableAlgorithmHelpers::ComputeMaxColumn(
+          colspan_cell_tabulator.CurrentColumn(), colspan, is_fixed_layout);
+      if (max_column >= cell_inline_constraints->size())
+        cell_inline_constraints->Grow(max_column);
+      if (!ignore_because_of_fixed_layout) {
+        NGBoxStrut cell_border = table_borders.CellBorder(
+            *row_index, colspan_cell_tabulator.CurrentColumn(),
+            cell.TableCellRowspan(), colspan, section_index, cell.Style());
+        NGBoxStrut cell_padding =
+            table_borders.CellPaddingForMeasure(cell.Style());
+        NGTableTypes::CellInlineConstraint cell_constraint =
+            NGTableTypes::CreateCellInlineConstraint(
+                cell, table_writing_mode, is_fixed_layout, cell_border,
+                cell_padding, table_borders.IsCollapsed());
+        if (colspan == 1) {
+          base::Optional<NGTableTypes::CellInlineConstraint>& constraint =
+              (*cell_inline_constraints)[colspan_cell_tabulator
+                                             .CurrentColumn()];
+          // Standard cell, update final column inline size values.
+          if (constraint.has_value()) {
+            constraint->Encompass(cell_constraint);
+          } else {
+            constraint = cell_constraint;
+          }
+        } else {
+          colspan_cell_inline_constraints->emplace_back(
+              cell_constraint, colspan_cell_tabulator.CurrentColumn(), colspan);
+        }
+      }
+      colspan_cell_tabulator.ProcessCell(cell);
+    }
+    is_first_row = false;
+    *row_index += 1;
+    colspan_cell_tabulator.EndRow();
+  }
+}
+
+void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes(
+    const NGBlockNode& section,
+    const LayoutUnit cell_percentage_inline_size,
+    const bool is_restricted_block_size_table,
+    const NGTableTypes::ColumnLocations& column_locations,
+    const NGTableBorders& table_borders,
+    const LayoutUnit block_border_spacing,
+    wtf_size_t section_index,
+    NGTableTypes::Sections* sections,
+    NGTableTypes::Rows* rows,
+    NGTableTypes::CellBlockConstraints* cell_block_constraints) {
+  wtf_size_t start_row = rows->size();
+  wtf_size_t current_row = start_row;
+  NGTableTypes::RowspanCells rowspan_cells;
+  LayoutUnit section_block_size;
+  // Used to compute column index.
+  NGColspanCellTabulator colspan_cell_tabulator;
+  // total_row_percent must be under 100%
+  float total_row_percent = 0;
+  // Get minimum block size of each row.
+  for (NGBlockNode row = To<NGBlockNode>(section.FirstChild()); row;
+       row = To<NGBlockNode>(row.NextSibling())) {
+    colspan_cell_tabulator.StartRow();
+    NGTableTypes::Row row_constraint = ComputeMinimumRowBlockSize(
+        row, cell_percentage_inline_size, is_restricted_block_size_table,
+        column_locations, table_borders, current_row++, section_index,
+        /* is_section_collapsed */ section.Style().Visibility() ==
+            EVisibility::kCollapse,
+        cell_block_constraints, &rowspan_cells, &colspan_cell_tabulator);
+    if (row_constraint.percent.has_value()) {
+      row_constraint.percent =
+          std::min(100.0f - total_row_percent, *row_constraint.percent);
+      total_row_percent += *row_constraint.percent;
+    }
+    rows->push_back(row_constraint);
+    section_block_size += row_constraint.block_size;
+    colspan_cell_tabulator.EndRow();
+  }
+  const wtf_size_t block_spacing_count =
+      current_row == start_row ? 0 : current_row - start_row - 1;
+  const LayoutUnit border_spacing_total =
+      block_border_spacing * block_spacing_count;
+  section_block_size += border_spacing_total;
+
+  // Redistribute rowspanned cell block sizes.
+  std::stable_sort(rowspan_cells.begin(), rowspan_cells.end());
+  for (NGTableTypes::RowspanCell& rowspan_cell : rowspan_cells) {
+    // Spec: rowspan of 0 means all remaining rows.
+    if (rowspan_cell.span == 0)
+      rowspan_cell.span = current_row - rowspan_cell.start_row;
+    // Truncate rows that are too long.
+    rowspan_cell.span =
+        std::min(current_row - rowspan_cell.start_row, rowspan_cell.span);
+    NGTableAlgorithmHelpers::DistributeRowspanCellToRows(
+        rowspan_cell, block_border_spacing, rows);
+  }
+
+  // Redistribute section's css block size.
+  const Length& section_specified_block_length =
+      section.Style().LogicalHeight();
+  // TODO(1105272) Handle section_specified_block_length.IsCalculated()
+  if (section_specified_block_length.IsFixed()) {
+    LayoutUnit section_fixed_block_size =
+        LayoutUnit(section_specified_block_length.Value());
+    if (section_fixed_block_size > section_block_size) {
+      NGTableAlgorithmHelpers::DistributeSectionFixedBlockSizeToRows(
+          start_row, current_row - start_row, section_fixed_block_size,
+          block_border_spacing, section_fixed_block_size, rows);
+      section_block_size = section_fixed_block_size;
+    }
+  }
+  sections->push_back(NGTableTypes::CreateSection(
+      section, start_row, current_row - start_row, section_block_size));
+}
+
+void NGColspanCellTabulator::StartRow() {
+  current_column_ = 0;
+}
+
+// Remove colspanned cells that are not spanning any more rows.
+void NGColspanCellTabulator::EndRow() {
+  for (wtf_size_t i = 0; i < colspanned_cells_.size();) {
+    colspanned_cells_[i].remaining_rows--;
+    if (colspanned_cells_[i].remaining_rows == 0)
+      colspanned_cells_.EraseAt(i);
+    else
+      ++i;
+  }
+}
+
+// Advance current column to position not occupied by colspanned cells.
+void NGColspanCellTabulator::FindNextFreeColumn() {
+  for (const Cell& colspanned_cell : colspanned_cells_) {
+    if (colspanned_cell.column_start <= current_column_ &&
+        colspanned_cell.column_start + colspanned_cell.span > current_column_) {
+      current_column_ = colspanned_cell.column_start + colspanned_cell.span;
+    }
+  }
+}
+
+void NGColspanCellTabulator::ProcessCell(const NGBlockNode& cell) {
+  wtf_size_t colspan = cell.TableCellColspan();
+  wtf_size_t rowspan = cell.TableCellRowspan();
+  if (rowspan > 1)
+    colspanned_cells_.emplace_back(current_column_, colspan, rowspan);
+  current_column_ += colspan;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h
new file mode 100644
index 0000000..00196c8b
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h
@@ -0,0 +1,103 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_NG_TABLE_LAYOUT_ALGORITHM_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_NG_TABLE_LAYOUT_ALGORITHM_UTILS_H_
+
+#include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.h"
+#include "third_party/blink/renderer/core/style/computed_style_constants.h"
+
+namespace blink {
+
+class NGTableBorders;
+class NGBlockNode;
+class NGBoxFragment;
+
+// Table size distribution algorithms.
+class NGTableAlgorithmUtils {
+ public:
+  static bool IsBaseline(EVerticalAlign align) {
+    return align == EVerticalAlign::kBaseline ||
+           align == EVerticalAlign::kBaselineMiddle ||
+           align == EVerticalAlign::kSub || align == EVerticalAlign::kSuper ||
+           align == EVerticalAlign::kTextTop ||
+           align == EVerticalAlign::kTextBottom ||
+           align == EVerticalAlign::kLength;
+  }
+
+  static LayoutUnit CellBaselineFromFragment(const NGBoxFragment& fragment);
+
+  static void ComputeColumnInlineConstraints(
+      const Vector<NGBlockNode>& columns,
+      bool is_fixed_layout,
+      NGTableTypes::Columns* column_constraints);
+
+  // Populate cell inline size constraints for a single section.
+  static void ComputeSectionInlineConstraints(
+      const NGBlockNode& section,
+      bool is_fixed_layout,
+      bool is_first_section,
+      WritingMode table_writing_mode,
+      const NGTableBorders& table_borders,
+      wtf_size_t section_index,
+      wtf_size_t* row_index,
+      NGTableTypes::CellInlineConstraints* cell_inline_constraints,
+      NGTableTypes::ColspanCells* colspan_cell_inline_constraints);
+
+  static void ComputeSectionMinimumRowBlockSizes(
+      const NGBlockNode& section,
+      const LayoutUnit cell_percentage_resolution_inline_size,
+      const bool is_restricted_block_size_table,
+      const NGTableTypes::ColumnLocations& column_locations,
+      const NGTableBorders& table_borders,
+      const LayoutUnit block_border_spacing,
+      wtf_size_t section_index,
+      NGTableTypes::Sections* sections,
+      NGTableTypes::Rows* rows,
+      NGTableTypes::CellBlockConstraints* cell_block_constraints);
+};
+
+// NGColspanCellTabulator keeps track of columns occupied by colspanned cells
+// when traversing rows in a section. It is used to compute cell's actual
+// column.
+// Usage:
+//   NGColspanCellTabulator colspan_cell_tabulator;
+//   for (Row r : section.rows) {
+//      colspan_cell_tabulator.StartRow();
+//      for (Cell c : row.cells) {
+//        colspan_cell_tabulator.FindNextFreeColumn();
+//        // colspan_cell_tabulator.CurrentColumn() has a valid value here.
+//        colspan_cell_tabulator.ProcessCell();
+//      }
+//      colspan_cell_tabulator.EndRow();
+//   }
+class NGColspanCellTabulator {
+ public:
+  unsigned CurrentColumn() { return current_column_; }
+  void StartRow();
+  void FindNextFreeColumn();
+  void ProcessCell(const NGBlockNode& cell);
+  void EndRow();
+
+  struct Cell {
+    Cell(unsigned column_start, unsigned span, unsigned remaining_rows)
+        : column_start(column_start),
+          span(span),
+          remaining_rows(remaining_rows) {}
+    unsigned column_start;
+    unsigned span;
+    unsigned remaining_rows;
+  };
+
+ private:
+  unsigned current_column_ = 0;
+  Vector<Cell> colspanned_cells_;
+};
+
+}  // namespace blink
+
+WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
+    blink::NGColspanCellTabulator::Cell)
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_NG_TABLE_LAYOUT_ALGORITHM_UTILS_H_
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index f205418..91b7df4 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1688,6 +1688,8 @@
 
       frame_->DomWindow()->SetOriginPolicyIds(ids);
     }
+  } else {
+    frame_->DomWindow()->ClearForReuse();
   }
 
   // Now that we have the final window and Agent, ensure the security origin has
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
index 34c003039..ade95ab 100644
--- a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -207,6 +207,9 @@
   if (object_.ShouldDoFullPaintInvalidation())
     return object_.FullPaintInvalidationReason();
 
+  if (context_.fragment_data->PaintOffset() != context_.old_paint_offset)
+    return PaintInvalidationReason::kGeometry;
+
   if (object_.GetDocument().InForcedColorsMode() && object_.IsLayoutBlockFlow())
     return PaintInvalidationReason::kBackplate;
 
@@ -215,16 +218,8 @@
   if (object_.StyleRef().BackgroundClip() == EFillBox::kText)
     return PaintInvalidationReason::kBackground;
 
-  // Most paintings are pixel-snapped so subpixel change of paint offset doesn't
-  // directly cause full raster invalidation.
-  if (RoundedIntPoint(context_.fragment_data->PaintOffset()) !=
-      RoundedIntPoint(context_.old_paint_offset))
-    return PaintInvalidationReason::kGeometry;
-
   // Incremental invalidation is only applicable to LayoutBoxes. Return
-  // PaintInvalidationIncremental no matter if oldVisualRect and newVisualRect
-  // are equal because a LayoutBox may need paint invalidation if its border box
-  // changes. BoxPaintInvalidator may also override this reason with a full
+  // kIncremental. BoxPaintInvalidator may override this reason with a full
   // paint invalidation reason if needed.
   if (object_.IsBox())
     return PaintInvalidationReason::kIncremental;
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
index 24ce10b..dcb84e6 100644
--- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
@@ -26,36 +26,6 @@
 using PaintControllerPaintTestForCAP = PaintControllerPaintTest;
 INSTANTIATE_CAP_TEST_SUITE_P(PaintControllerPaintTestForCAP);
 
-TEST_P(PaintControllerPaintTest, FullDocumentPaintingWithCaret) {
-  SetBodyInnerHTML(
-      "<div id='div' contentEditable='true' style='outline:none'>XYZ</div>");
-  GetDocument().GetPage()->GetFocusController().SetActive(true);
-  GetDocument().GetPage()->GetFocusController().SetFocused(true);
-  auto& div = *To<Element>(GetDocument().body()->firstChild());
-  auto& layout_text = *To<Text>(div.firstChild())->GetLayoutObject();
-  const DisplayItemClient* text_inline_box = layout_text.FirstTextBox();
-  if (layout_text.IsInLayoutNGInlineFormattingContext()) {
-    NGInlineCursor cursor;
-    cursor.MoveTo(layout_text);
-    text_inline_box = cursor.Current().GetDisplayItemClient();
-  }
-  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
-              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
-                                   kDocumentBackgroundType),
-                          IsSameId(text_inline_box, kForegroundType)));
-
-  div.focus();
-  UpdateAllLifecyclePhasesForTest();
-
-  EXPECT_THAT(
-      RootPaintController().GetDisplayItemList(),
-      ElementsAre(
-          IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-          IsSameId(text_inline_box, kForegroundType),
-          // New!
-          IsSameId(&CaretDisplayItemClientForTesting(), DisplayItem::kCaret)));
-}
-
 TEST_P(PaintControllerPaintTest, InlineRelayout) {
   SetBodyInnerHTML(
       "<div id='div' style='width:100px; height: 200px'>AAAAAAAAAA "
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
index f87c116..fd47ea5 100644
--- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
+++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
@@ -100,13 +100,6 @@
     return RootPaintController().num_cached_new_items_;
   }
 
-  const DisplayItemClient& CaretDisplayItemClientForTesting() const {
-    return GetDocument()
-        .GetFrame()
-        ->Selection()
-        .CaretDisplayItemClientForTesting();
-  }
-
   void InvalidateAll(PaintController& paint_controller) {
     paint_controller.InvalidateAllForTesting();
     if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc
index 54bd89d..0019b34 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -32,44 +32,6 @@
 
 namespace blink {
 
-// If needed, exclude composited layer's subpixel accumulation to avoid full
-// layer raster invalidations during animation with subpixels.
-// See crbug.com/833083 for details.
-bool PaintInvalidatorContext::ShouldExcludeCompositedLayerSubpixelAccumulation(
-    const LayoutObject& object) const {
-  // TODO(wangxianzhu): How to handle sub-pixel location animation for CAP?
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
-    return false;
-
-  // One of the following conditions happened in crbug.com/837226.
-  if (!directly_composited_container ||
-      !directly_composited_container->FirstFragment()
-           .HasLocalBorderBoxProperties() ||
-      !tree_builder_context_)
-    return false;
-
-  if (!directly_composited_container->Layer()
-           ->CanBeCompositedForDirectReasons())
-    return false;
-
-  if (object != directly_composited_container &&
-      &directly_composited_container->FirstFragment().PostScrollTranslation() !=
-          tree_builder_context_->current.transform) {
-    // Subpixel accumulation doesn't propagate through non-translation
-    // transforms. Also skip all transforms, to avoid the runtime cost of
-    // verifying whether the transform is a translation.
-    return false;
-  }
-
-  // Will exclude the subpixel accumulation so that the paint invalidator won't
-  // see changed visual rects during composited animation with subpixels, to
-  // avoid full layer invalidation. The subpixel accumulation will be added
-  // back in ChunkToLayerMapper::AdjustVisualRectBySubpixelOffset(). Should
-  // make sure the code is synced.
-  // TODO(wangxianzhu): Avoid exposing subpixel accumulation to platform code.
-  return true;
-}
-
 IntRect PaintInvalidatorContext::MapLocalRectToVisualRect(
     const LayoutObject& object,
     const PhysicalRect& local_rect) const {
@@ -95,8 +57,7 @@
     rect.Unite(PhysicalRect(EnclosingIntRect(*clip_path_bounding_box)));
 
   rect.Move(fragment_data->PaintOffset());
-  if (ShouldExcludeCompositedLayerSubpixelAccumulation(object))
-    rect.Move(-directly_composited_container->Layer()->SubpixelAccumulation());
+
   // Use EnclosingIntRect to ensure the final visual rect will cover the rect
   // in source coordinates no matter if the painting will snap to pixels.
   return EnclosingIntRect(rect);
@@ -115,14 +76,7 @@
   // input rect is in local SVG coordinates in which paint offset doesn't apply.
   // We also don't need to adjust for clip path here because SVG the local
   // visual rect has already been adjusted by clip path.
-  auto rect = local_rect;
-  if (ShouldExcludeCompositedLayerSubpixelAccumulation(object)) {
-    rect.Move(FloatSize(
-        -directly_composited_container->Layer()->SubpixelAccumulation()));
-  }
-  // Use EnclosingIntRect to ensure the final visual rect will cover the rect
-  // in source coordinates no matter if the painting will snap to pixels.
-  return EnclosingIntRect(rect);
+  return EnclosingIntRect(local_rect);
 }
 
 const PaintInvalidatorContext*
@@ -303,6 +257,14 @@
       old_visual_rect, new_visual_rect,
       FloatSize(context.old_offset_to_2d_translation_root -
                 fragment_data.OffsetTo2DTranslationRoot()));
+
+  // For performance, we ignore subpixel movement of composited layers for paint
+  // invalidation. This will result in imperfect pixel-snapped painting.
+  // See crbug.com/833083 for details.
+  if (context.tree_builder_context_->current
+          .directly_composited_container_paint_offset_subpixel_delta ==
+      fragment_data.PaintOffset() - context.old_paint_offset)
+    context.old_paint_offset = fragment_data.PaintOffset();
 }
 
 void PaintInvalidator::UpdateEmptyVisualRectFlag(
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.h b/third_party/blink/renderer/core/paint/paint_invalidator.h
index 8be4cf9..03eeb5c 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.h
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -134,9 +134,6 @@
  private:
   friend class PaintInvalidator;
 
-  bool ShouldExcludeCompositedLayerSubpixelAccumulation(
-      const LayoutObject&) const;
-
   const PaintPropertyTreeBuilderFragmentContext* tree_builder_context_ =
       nullptr;
 
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 49c2717..5c68a3ce 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -458,27 +458,61 @@
   // In pre-CompositeAfterPaint, if the object has layer, this corresponds to
   // PaintLayer::SubpixelAccumulation().
   paint_offset_translation = RoundedIntPoint(context_.current.paint_offset);
-  PhysicalOffset subpixel_accumulation;
   // Don't propagate subpixel accumulation through paint isolation. In
   // pre-CompositeAfterPaint we still need to keep consistence with the legacy
   // compositing code.
-  if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
-      !NeedsIsolationNodes(object_)) {
-    subpixel_accumulation = context_.current.paint_offset -
-                            PhysicalOffset(*paint_offset_translation);
-    if (!subpixel_accumulation.IsZero()) {
-      // If the object has a non-translation transform, discard the fractional
-      // paint offset which can't be transformed by the transform.
-      TransformationMatrix matrix;
-      object_.StyleRef().ApplyTransform(
-          matrix, LayoutSize(), ComputedStyle::kExcludeTransformOrigin,
-          ComputedStyle::kIncludeMotionPath,
-          ComputedStyle::kIncludeIndependentTransformProperties);
-      if (!matrix.IsIdentityOrTranslation())
-        subpixel_accumulation = PhysicalOffset();
+  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+      NeedsIsolationNodes(object_)) {
+    context_.current.paint_offset = PhysicalOffset();
+    context_.current.directly_composited_container_paint_offset_subpixel_delta =
+        PhysicalOffset();
+    return;
+  }
+
+  PhysicalOffset subpixel_accumulation =
+      context_.current.paint_offset - PhysicalOffset(*paint_offset_translation);
+  if (!subpixel_accumulation.IsZero() ||
+      !context_.current
+           .directly_composited_container_paint_offset_subpixel_delta
+           .IsZero()) {
+    // If the object has a non-translation transform, discard the fractional
+    // paint offset which can't be transformed by the transform.
+    TransformationMatrix matrix;
+    object_.StyleRef().ApplyTransform(
+        matrix, LayoutSize(), ComputedStyle::kExcludeTransformOrigin,
+        ComputedStyle::kIncludeMotionPath,
+        ComputedStyle::kIncludeIndependentTransformProperties);
+    if (!matrix.IsIdentityOrTranslation()) {
+      context_.current.paint_offset = PhysicalOffset();
+      context_.current
+          .directly_composited_container_paint_offset_subpixel_delta =
+          PhysicalOffset();
+      return;
     }
   }
+
   context_.current.paint_offset = subpixel_accumulation;
+
+  bool can_be_directly_composited =
+      RuntimeEnabledFeatures::CompositeAfterPaintEnabled()
+          ? full_context_.direct_compositing_reasons != CompositingReason::kNone
+          : object_.CanBeCompositedForDirectReasons();
+  if (!can_be_directly_composited)
+    return;
+
+  if (paint_offset_translation && properties_ &&
+      properties_->PaintOffsetTranslation()) {
+    // The composited subpixel movement optimization applies only if the
+    // composited layer has and had PaintOffsetTranslation, so that both the
+    // the old and new paint offsets are just subpixel accumulations.
+    DCHECK_EQ(IntPoint(), RoundedIntPoint(fragment_data_.PaintOffset()));
+    context_.current.directly_composited_container_paint_offset_subpixel_delta =
+        context_.current.paint_offset - fragment_data_.PaintOffset();
+  } else {
+    // Otherwise disable the optimization.
+    context_.current.directly_composited_container_paint_offset_subpixel_delta =
+        PhysicalOffset();
+  }
 }
 
 void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
@@ -1829,6 +1863,8 @@
     // SVG painters don't use paint offset. The paint offset is baked into
     // the transform node instead.
     context_.current.paint_offset = PhysicalOffset();
+    context_.current.directly_composited_container_paint_offset_subpixel_delta =
+        PhysicalOffset();
 
     // Only <svg> paints its subtree as replaced contents. Other replaced
     // element type may have shadow DOM that should not be affected by the
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
index c3f125e..a30fea0 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -56,6 +56,12 @@
     // of the 2D translation root.
     PhysicalOffset offset_to_2d_translation_root;
 
+    // For paint invalidation optimization for subpixel movement under
+    // composited layer. It's reset to zero if subpixel can't be propagated
+    // thus the optimization is not applicable (e.g. when crossing a
+    // non-translation transform).
+    PhysicalOffset directly_composited_container_paint_offset_subpixel_delta;
+
     // The PaintLayer corresponding to the origin of |paint_offset|.
     const LayoutObject* paint_offset_root = nullptr;
     // Whether newly created children should flatten their inherited transform
@@ -64,6 +70,10 @@
     // to immediate children.
     bool should_flatten_inherited_transform = false;
 
+    // True if any fixed-position children within this context are fixed to the
+    // root of the FrameView (and hence above its scroll).
+    bool fixed_position_children_fixed_to_root = false;
+
     // Rendering context for 3D sorting. See
     // TransformPaintPropertyNode::renderingContextId.
     unsigned rendering_context_id = 0;
@@ -78,10 +88,6 @@
     // reference a scroll offset transform, scroll nodes should be updated if
     // the transform tree changes.
     const ScrollPaintPropertyNode* scroll = nullptr;
-
-    // True if any fixed-position children within this context are fixed to the
-    // root of the FrameView (and hence above its scroll).
-    bool fixed_position_children_fixed_to_root = false;
   };
 
   ContainingBlockContext current;
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index b829a2d..c6ce16db 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -850,11 +850,14 @@
       if (auto* embedded_view =
               layout_embedded_content.GetEmbeddedContentView()) {
         if (context().tree_builder_context) {
-          auto& offset =
-              context().tree_builder_context->fragments[0].current.paint_offset;
-          offset += layout_embedded_content.ReplacedContentRect().offset;
-          offset -= PhysicalOffset(embedded_view->FrameRect().Location());
-          offset = PhysicalOffset(RoundedIntPoint(offset));
+          auto& current = context().tree_builder_context->fragments[0].current;
+          current.paint_offset = PhysicalOffset(RoundedIntPoint(
+              current.paint_offset +
+              layout_embedded_content.ReplacedContentRect().offset -
+              PhysicalOffset(embedded_view->FrameRect().Location())));
+          // Subpixel accumulation doesn't propagate across embedded view.
+          current.directly_composited_container_paint_offset_subpixel_delta =
+              PhysicalOffset();
         }
         if (embedded_view->IsLocalFrameView()) {
           Walk(*To<LocalFrameView>(embedded_view));
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc
index dd83420c..c8efda5d 100644
--- a/third_party/blink/renderer/core/timing/performance.cc
+++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -241,6 +241,7 @@
   PerformanceEntryVector entries;
   switch (type) {
     case PerformanceEntry::kResource:
+      UseCounter::Count(GetExecutionContext(), WebFeature::kResourceTiming);
       for (const auto& resource : resource_timing_buffer_)
         entries.push_back(resource);
       break;
@@ -263,6 +264,7 @@
         entries.push_back(first_input_timing_);
       break;
     case PerformanceEntry::kNavigation:
+      UseCounter::Count(GetExecutionContext(), WebFeature::kNavigationTimingL2);
       if (!navigation_timing_)
         navigation_timing_ = CreateNavigationTimingInstance();
       if (navigation_timing_)
diff --git a/third_party/blink/renderer/core/timing/performance_observer.cc b/third_party/blink/renderer/core/timing/performance_observer.cc
index 8881ef7..29591712 100644
--- a/third_party/blink/renderer/core/timing/performance_observer.cc
+++ b/third_party/blink/renderer/core/timing/performance_observer.cc
@@ -204,6 +204,9 @@
     UseCounter::Count(GetExecutionContext(),
                       WebFeature::kLargestContentfulPaintExplicitlyRequested);
   }
+  if (filter_options_ & PerformanceEntry::kResource) {
+    UseCounter::Count(GetExecutionContext(), WebFeature::kResourceTiming);
+  }
   if (is_registered_)
     performance_->UpdatePerformanceObserverFilterOptions();
   else
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 076e249..46a31f38 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -800,6 +800,25 @@
   if (GetTextAlign() != ax::mojom::blink::TextAlign::kNone) {
     node_data->SetTextAlign(GetTextAlign());
   }
+
+  // If this is an HTMLFrameOwnerElement (such as an iframe), we may need
+  // to embed the ID of the child frame.
+  if (auto* html_frame_owner_element =
+          DynamicTo<HTMLFrameOwnerElement>(GetElement())) {
+    base::Optional<base::UnguessableToken> child_token =
+        html_frame_owner_element->GetEmbeddingToken();
+
+    // Only add the attribute for the embedding token if there aren't children,
+    // because if there are children, the fallback content has been rendered
+    // and should be used instead. For example, the fallback content may be
+    // rendered if there was an error loading an <object>. The AXNodeData
+    // should not have both children and a child tree.
+    if (child_token && !(IsDetached() || ChildCountIncludingIgnored())) {
+      node_data->AddStringAttribute(
+          ax::mojom::blink::StringAttribute::kChildTreeId,
+          child_token->ToString());
+    }
+  }
 }
 
 bool AXObject::IsAXNodeObject() const {
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn
index 4979bfb..9eeec16 100644
--- a/third_party/blink/renderer/modules/mediastream/BUILD.gn
+++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -45,8 +45,8 @@
     "media_stream_event.h",
     "media_stream_local_frame_wrapper.cc",
     "media_stream_local_frame_wrapper.h",
-    "media_stream_renderer_factory_impl.cc",
-    "media_stream_renderer_factory_impl.h",
+    "media_stream_renderer_factory.cc",
+    "media_stream_renderer_factory.h",
     "media_stream_track.cc",
     "media_stream_track.h",
     "media_stream_track_content_hint.h",
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
index a327f1c1..bbe1349e 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
@@ -9,7 +9,6 @@
 #include <string>
 #include <tuple>
 #include <utility>
-#include <vector>
 
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
@@ -26,8 +25,6 @@
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
 
-// TODO(crbug.com/704136): Replace the use of std::vector by WTF::Vector.
-
 namespace blink {
 
 using blink::AudioCaptureSettings;
@@ -305,7 +302,7 @@
         device_parameters_(media::AudioParameters::UnavailableDeviceParams()),
         is_device_capture_(true) {}
 
-  EchoCancellationContainer(std::vector<EchoCancellationType> allowed_values,
+  EchoCancellationContainer(Vector<EchoCancellationType> allowed_values,
                             bool has_active_source,
                             bool is_device_capture,
                             media::AudioParameters device_parameters,
@@ -428,7 +425,7 @@
   }
 
   static EchoCancellationTypeSet ToEchoCancellationTypes(const BoolSet ec_set) {
-    std::vector<EchoCancellationType> types;
+    Vector<EchoCancellationType> types;
 
     if (ec_set.Contains(false))
       types.push_back(EchoCancellationType::kEchoCancellationDisabled);
@@ -884,22 +881,21 @@
   // System echo cancellation should not be explicitly included in
   // |echo_cancellation_type|. It is added automatically based on the value of
   // |device_parameters|.
-  ProcessingBasedContainer(
-      ProcessingType processing_type,
-      std::vector<EchoCancellationType> echo_cancellation_types,
-      BoolSet auto_gain_control_set,
-      BoolSet goog_audio_mirroring_set,
-      BoolSet goog_experimental_echo_cancellation_set,
-      BoolSet goog_noise_suppression_set,
-      BoolSet goog_experimental_noise_suppression_set,
-      BoolSet goog_highpass_filter_set,
-      IntRangeSet sample_size_range,
-      IntRangeSet channels_range,
-      IntRangeSet sample_rate_range,
-      SourceInfo source_info,
-      bool is_device_capture,
-      media::AudioParameters device_parameters,
-      bool is_reconfiguration_allowed)
+  ProcessingBasedContainer(ProcessingType processing_type,
+                           Vector<EchoCancellationType> echo_cancellation_types,
+                           BoolSet auto_gain_control_set,
+                           BoolSet goog_audio_mirroring_set,
+                           BoolSet goog_experimental_echo_cancellation_set,
+                           BoolSet goog_noise_suppression_set,
+                           BoolSet goog_experimental_noise_suppression_set,
+                           BoolSet goog_highpass_filter_set,
+                           IntRangeSet sample_size_range,
+                           IntRangeSet channels_range,
+                           IntRangeSet sample_rate_range,
+                           SourceInfo source_info,
+                           bool is_device_capture,
+                           media::AudioParameters device_parameters,
+                           bool is_reconfiguration_allowed)
       : processing_type_(processing_type),
         sample_size_container_(sample_size_range),
         channels_container_(channels_range),
@@ -1094,7 +1090,7 @@
 
     // For each processing based container, apply the constraints and only fail
     // if all of them failed.
-    for (auto it = processing_based_containers_.begin();
+    for (auto* it = processing_based_containers_.begin();
          it != processing_based_containers_.end();) {
       DCHECK(!it->IsEmpty());
       failed_constraint_name = it->ApplyConstraintSet(constraint_set);
@@ -1103,7 +1099,7 @@
       else
         ++it;
     }
-    if (processing_based_containers_.empty()) {
+    if (processing_based_containers_.IsEmpty()) {
       DCHECK_NE(failed_constraint_name, nullptr);
       return failed_constraint_name;
     }
@@ -1268,7 +1264,7 @@
   StringContainer device_id_container_;
   StringContainer group_id_container_;
   std::array<BooleanContainer, kNumBooleanContainerIds> boolean_containers_;
-  std::vector<ProcessingBasedContainer> processing_based_containers_;
+  Vector<ProcessingBasedContainer> processing_based_containers_;
 };
 
 constexpr DeviceContainer::BooleanPropertyContainerInfo
@@ -1301,7 +1297,7 @@
 
   const char* ApplyConstraintSet(const ConstraintSet& constraint_set) {
     const char* latest_failed_constraint_name = nullptr;
-    for (auto it = devices_.begin(); it != devices_.end();) {
+    for (auto* it = devices_.begin(); it != devices_.end();) {
       DCHECK(!it->IsEmpty());
       auto* failed_constraint_name = it->ApplyConstraintSet(constraint_set);
       if (failed_constraint_name) {
@@ -1339,11 +1335,11 @@
     return std::make_tuple(best_score, best_settings);
   }
 
-  bool IsEmpty() const { return devices_.empty(); }
+  bool IsEmpty() const { return devices_.IsEmpty(); }
 
  private:
   std::string default_device_id_;
-  std::vector<DeviceContainer> devices_;
+  Vector<DeviceContainer> devices_;
 };
 
 std::string GetMediaStreamSource(const MediaConstraints& constraints) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.cc
index 88e92c1..71dc2f3 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.cc
@@ -95,9 +95,9 @@
 // |vertices| must have 1 or 2 elements. Otherwise, behavior is undefined.
 // This function is called when |point| has already been determined to be
 // outside a polygon and |vertices| is the vertex or side closest to |point|.
-Point GetClosestPointToVertexOrSide(const std::vector<Point> vertices,
+Point GetClosestPointToVertexOrSide(const Vector<Point> vertices,
                                     const Point& point) {
-  DCHECK(!vertices.empty());
+  DCHECK(!vertices.IsEmpty());
   // If only a single vertex closest to |point|, return that vertex.
   if (vertices.size() == 1U)
     return vertices[0];
@@ -309,7 +309,7 @@
           return intersection.ClosestPointTo(
               Point(ideal_height, ideal_height * default_aspect_ratio));
         }
-        std::vector<Point> closest_vertices =
+        Vector<Point> closest_vertices =
             GetClosestVertices(&Point::height, ideal_height);
         Point ideal_point(closest_vertices[0].height(),
                           closest_vertices[0].height() * default_aspect_ratio);
@@ -323,7 +323,7 @@
           return intersection.ClosestPointTo(
               Point(ideal_width / default_aspect_ratio, ideal_width));
         }
-        std::vector<Point> closest_vertices =
+        Vector<Point> closest_vertices =
             GetClosestVertices(&Point::width, ideal_width);
         Point ideal_point(closest_vertices[0].width() / default_aspect_ratio,
                           closest_vertices[0].width());
@@ -379,7 +379,7 @@
         intersection.ClosestPointTo(default_height_point),
         intersection.ClosestPointTo(default_width_point));
   }
-  std::vector<Point> closest_vertices =
+  Vector<Point> closest_vertices =
       GetClosestVertices(&Point::AspectRatio, ideal_aspect_ratio);
   double actual_aspect_ratio = closest_vertices[0].AspectRatio();
   Point default_height_point(default_height,
@@ -402,7 +402,7 @@
   DCHECK_GE(vertices.size(), 1U);
   Point best_candidate(0, 0);
   double best_distance = HUGE_VAL;
-  for (size_t i = 0; i < vertices.size(); ++i) {
+  for (WTF::wtf_size_t i = 0; i < vertices.size(); ++i) {
     Point candidate = Point::ClosestPointInSegment(
         point, vertices[i], vertices[(i + 1) % vertices.size()]);
     double distance = Point::SquareEuclideanDistance(point, candidate);
@@ -416,12 +416,12 @@
   return best_candidate;
 }
 
-std::vector<Point> ResolutionSet::GetClosestVertices(double (Point::*accessor)()
-                                                         const,
-                                                     double value) const {
+Vector<Point> ResolutionSet::GetClosestVertices(double (Point::*accessor)()
+                                                    const,
+                                                double value) const {
   DCHECK(!IsEmpty());
-  std::vector<Point> vertices = ComputeVertices();
-  std::vector<Point> closest_vertices;
+  Vector<Point> vertices = ComputeVertices();
+  Vector<Point> closest_vertices;
   double best_diff = HUGE_VAL;
   for (const auto& vertex : vertices) {
     double diff;
@@ -437,7 +437,7 @@
       closest_vertices.push_back(vertex);
     }
   }
-  DCHECK(!closest_vertices.empty());
+  DCHECK(!closest_vertices.IsEmpty());
   DCHECK_LE(closest_vertices.size(), 2U);
   return closest_vertices;
 }
@@ -481,8 +481,8 @@
                        std::isnan(aspect_ratio) ? HUGE_VAL : aspect_ratio);
 }
 
-std::vector<Point> ResolutionSet::ComputeVertices() const {
-  std::vector<Point> vertices;
+Vector<Point> ResolutionSet::ComputeVertices() const {
+  Vector<Point> vertices;
   // Add vertices in counterclockwise order
   // Start with (min_height, min_width) and continue along min_width.
   TryAddVertex(&vertices, Point(min_height_, min_width_));
@@ -521,7 +521,7 @@
   return vertices;
 }
 
-void ResolutionSet::TryAddVertex(std::vector<Point>* vertices,
+void ResolutionSet::TryAddVertex(Vector<Point>* vertices,
                                  const Point& point) const {
   if (!ContainsPoint(point))
     return;
@@ -529,7 +529,7 @@
   // Add the point to the |vertices| if not already added.
   // This is to prevent duplicates in case an aspect ratio intersects a width
   // or height right on a vertex.
-  if (vertices->empty() ||
+  if (vertices->IsEmpty() ||
       (*(vertices->end() - 1) != point && *vertices->begin() != point)) {
     vertices->push_back(point);
   }
@@ -551,7 +551,7 @@
   if (!constraint.HasExact())
     return DiscreteSet<std::string>::UniversalSet();
 
-  std::vector<std::string> elements;
+  Vector<std::string> elements;
   for (const auto& entry : constraint.Exact())
     elements.push_back(entry.Ascii());
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.h b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.h
index ad388e20..0a397cb 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets.h
@@ -9,13 +9,13 @@
 #include <limits>
 #include <string>
 #include <utility>
-#include <vector>
 
 #include "base/check_op.h"
 #include "base/gtest_prod_util.h"
 #include "base/optional.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
@@ -151,10 +151,10 @@
   // It is the responsibility of the caller to ensure that |elements| is not
   // equivalent to the universal set and that |elements| has no repeated
   // values. Takes ownership of |elements|.
-  explicit DiscreteSet(std::vector<T> elements)
+  explicit DiscreteSet(Vector<T> elements)
       : is_universal_(false), elements_(std::move(elements)) {}
   // Creates an empty set;
-  static DiscreteSet EmptySet() { return DiscreteSet(std::vector<T>()); }
+  static DiscreteSet EmptySet() { return DiscreteSet(Vector<T>()); }
   static DiscreteSet UniversalSet() { return DiscreteSet(); }
 
   DiscreteSet(const DiscreteSet& other) = default;
@@ -167,9 +167,9 @@
     return is_universal_ || base::Contains(elements_, value);
   }
 
-  bool IsEmpty() const { return !is_universal_ && elements_.empty(); }
+  bool IsEmpty() const { return !is_universal_ && elements_.IsEmpty(); }
 
-  bool HasExplicitElements() const { return !elements_.empty(); }
+  bool HasExplicitElements() const { return !elements_.IsEmpty(); }
 
   DiscreteSet Intersection(const DiscreteSet& other) const {
     if (is_universal_)
@@ -180,7 +180,7 @@
       return EmptySet();
 
     // Both sets have explicit elements.
-    std::vector<T> intersection;
+    Vector<T> intersection;
     for (const auto& entry : elements_) {
       if (base::Contains(other.elements_, entry))
         intersection.push_back(entry);
@@ -198,7 +198,7 @@
 
   // Returns a reference to the list of elements in the set.
   // Behavior is undefined if the set is universal.
-  const std::vector<T>& elements() const {
+  const Vector<T>& elements() const {
     DCHECK(!is_universal_);
     return elements_;
   }
@@ -207,7 +207,7 @@
 
  private:
   bool is_universal_;
-  std::vector<T> elements_;
+  Vector<T> elements_;
 };
 
 // Special case for DiscreteSet<bool> where it is easy to produce an explicit
@@ -413,7 +413,7 @@
   // consecutive vertices (modulo the size of the list) corresponds to a side of
   // the polygon, with the vertices given in counterclockwise order.
   // The list cannot contain more than six points.
-  std::vector<Point> ComputeVertices() const;
+  Vector<Point> ComputeVertices() const;
 
  private:
   // Implements SelectClosestPointToIdeal() for the case when only the ideal
@@ -425,11 +425,11 @@
   // Returns the vertices of the set that have the property accessed
   // by |accessor| closest to |value|. The returned vector always has one or two
   // elements. Behavior is undefined if the set is empty.
-  std::vector<Point> GetClosestVertices(double (Point::*accessor)() const,
-                                        double value) const;
+  Vector<Point> GetClosestVertices(double (Point::*accessor)() const,
+                                   double value) const;
 
   // Adds |point| to |vertices| if |point| is included in this candidate set.
-  void TryAddVertex(std::vector<ResolutionSet::Point>* vertices,
+  void TryAddVertex(Vector<ResolutionSet::Point>* vertices,
                     const ResolutionSet::Point& point) const;
 
   int min_height_;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets_test.cc
index 9fd6f85d..d9815c9 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_sets_test.cc
@@ -6,7 +6,6 @@
 
 #include <cmath>
 #include <string>
-#include <vector>
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h"
@@ -36,7 +35,7 @@
 
 // Checks if |point| is an element of |vertices| using
 // Point::IsApproximatelyEqualTo() to test for equality.
-void VerticesContain(const std::vector<Point>& vertices, const Point& point) {
+void VerticesContain(const Vector<Point>& vertices, const Point& point) {
   bool result = false;
   for (const auto& vertex : vertices) {
     if (point.IsApproximatelyEqualTo(vertex)) {
@@ -47,7 +46,7 @@
   EXPECT_TRUE(result);
 }
 
-bool AreCounterclockwise(const std::vector<Point>& vertices) {
+bool AreCounterclockwise(const Vector<Point>& vertices) {
   // Single point or segment are trivial cases.
   if (vertices.size() <= 2)
     return true;
@@ -63,7 +62,8 @@
   // Compute orientation using the determinant of each diagonal in the
   // polygon, using the first vertex as reference.
   Point prev_diagonal = vertices[1] - vertices[0];
-  for (auto vertex = vertices.begin() + 2; vertex != vertices.end(); ++vertex) {
+  for (auto* vertex = vertices.begin() + 2; vertex != vertices.end();
+       ++vertex) {
     Point current_diagonal = *vertex - vertices[0];
     // The determinant of the two diagonals returns the signed area of the
     // parallelogram they generate. The area is positive if the diagonals are in
@@ -81,8 +81,7 @@
 
 // Determines if |vertices| is valid according to the contract for
 // ResolutionCandidateSet::ComputeVertices().
-bool AreValidVertices(const ResolutionSet& set,
-                      const std::vector<Point>& vertices) {
+bool AreValidVertices(const ResolutionSet& set, const Vector<Point>& vertices) {
   // Verify that every vertex is included in |set|.
   for (const auto& vertex : vertices) {
     if (!set.ContainsPoint(vertex))
@@ -1370,7 +1369,7 @@
   EXPECT_FALSE(set.HasExplicitElements());
 
   // Constrained set.
-  set = StringSet(std::vector<std::string>({"a", "b", "c"}));
+  set = StringSet(Vector<std::string>({"a", "b", "c"}));
   EXPECT_TRUE(set.Contains("a"));
   EXPECT_TRUE(set.Contains("b"));
   EXPECT_TRUE(set.Contains("c"));
@@ -1389,8 +1388,8 @@
   EXPECT_FALSE(set.HasExplicitElements());
 
   // Intersection.
-  set = StringSet(std::vector<std::string>({"a", "b", "c"}));
-  StringSet set2 = StringSet(std::vector<std::string>({"b", "c", "d"}));
+  set = StringSet(Vector<std::string>({"a", "b", "c"}));
+  StringSet set2 = StringSet(Vector<std::string>({"b", "c", "d"}));
   auto intersection = set.Intersection(set2);
   EXPECT_FALSE(intersection.Contains("a"));
   EXPECT_TRUE(intersection.Contains("b"));
@@ -1402,7 +1401,7 @@
   EXPECT_EQ(std::string("b"), intersection.FirstElement());
 
   // Empty intersection.
-  set2 = StringSet(std::vector<std::string>({"d", "e", "f"}));
+  set2 = StringSet(Vector<std::string>({"d", "e", "f"}));
   intersection = set.Intersection(set2);
   EXPECT_FALSE(intersection.Contains("a"));
   EXPECT_FALSE(intersection.Contains("b"));
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.cc
similarity index 95%
rename from third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc
rename to third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.cc
index b90c6ad..820131a 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.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 "third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.h"
+#include "third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h"
 
 #include <utility>
 
@@ -47,19 +47,19 @@
 
 }  // namespace
 
-MediaStreamRendererFactoryImpl::MediaStreamRendererFactoryImpl() {}
+MediaStreamRendererFactory::MediaStreamRendererFactory() {}
 
-MediaStreamRendererFactoryImpl::~MediaStreamRendererFactoryImpl() {}
+MediaStreamRendererFactory::~MediaStreamRendererFactory() {}
 
 scoped_refptr<WebMediaStreamVideoRenderer>
-MediaStreamRendererFactoryImpl::GetVideoRenderer(
+MediaStreamRendererFactory::GetVideoRenderer(
     const WebMediaStream& web_stream,
     const WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner) {
   DCHECK(!web_stream.IsNull());
 
-  DVLOG(1) << "MediaStreamRendererFactoryImpl::GetVideoRenderer stream:"
+  DVLOG(1) << "MediaStreamRendererFactory::GetVideoRenderer stream:"
            << web_stream.Id().Utf8();
 
   MediaStreamDescriptor& descriptor = *web_stream;
@@ -76,7 +76,7 @@
 }
 
 scoped_refptr<WebMediaStreamAudioRenderer>
-MediaStreamRendererFactoryImpl::GetAudioRenderer(
+MediaStreamRendererFactory::GetAudioRenderer(
     const WebMediaStream& web_stream,
     WebLocalFrame* web_frame,
     const WebString& device_id,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h
new file mode 100644
index 0000000..633ecd7
--- /dev/null
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_RENDERER_FACTORY_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_RENDERER_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_renderer.h"
+#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_video_renderer.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace blink {
+
+class WebMediaStream;
+class WebLocalFrame;
+
+// MediaStreamRendererFactory is used by WebMediaPlayerMS to create audio
+// and video feeds from a MediaStream provided an URL. The factory methods are
+// virtual in order for Blink web tests to be able to override them.
+class MODULES_EXPORT MediaStreamRendererFactory {
+ public:
+  MediaStreamRendererFactory();
+  virtual ~MediaStreamRendererFactory();
+
+  virtual scoped_refptr<WebMediaStreamVideoRenderer> GetVideoRenderer(
+      const WebMediaStream& web_stream,
+      const WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
+      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner);
+
+  virtual scoped_refptr<WebMediaStreamAudioRenderer> GetAudioRenderer(
+      const WebMediaStream& web_stream,
+      WebLocalFrame* web_frame,
+      const WebString& device_id,
+      base::RepeatingCallback<void()> on_render_error_callback);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MediaStreamRendererFactory);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_RENDERER_FACTORY_H_
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.h b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.h
deleted file mode 100644
index e9e44db..0000000
--- a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
-
-#include "base/macros.h"
-#include "third_party/blink/public/web/modules/mediastream/web_media_stream_renderer_factory.h"
-
-namespace blink {
-
-class MediaStreamRendererFactoryImpl : public WebMediaStreamRendererFactory {
- public:
-  MediaStreamRendererFactoryImpl();
-  ~MediaStreamRendererFactoryImpl() override;
-
-  scoped_refptr<WebMediaStreamVideoRenderer> GetVideoRenderer(
-      const WebMediaStream& web_stream,
-      const WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
-      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner)
-      override;
-
-  scoped_refptr<WebMediaStreamAudioRenderer> GetAudioRenderer(
-      const WebMediaStream& web_stream,
-      WebLocalFrame* web_frame,
-      const WebString& device_id,
-      base::RepeatingCallback<void()> on_render_error_callback) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MediaStreamRendererFactoryImpl);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
diff --git a/third_party/blink/renderer/modules/mediastream/track_audio_renderer.h b/third_party/blink/renderer/modules/mediastream/track_audio_renderer.h
index 5f5532c..bd4452f 100644
--- a/third_party/blink/renderer/modules/mediastream/track_audio_renderer.h
+++ b/third_party/blink/renderer/modules/mediastream/track_audio_renderer.h
@@ -36,7 +36,7 @@
 // PeerConnection/WebRTC-sourced) MediaStreamAudioTracks to an audio output
 // device, reconciling differences in the rates of production and consumption of
 // the audio data.  Note that remote PeerConnection-sourced tracks are NOT
-// rendered by this implementation (see WebMediaStreamRendererFactoryImpl).
+// rendered by this implementation (see MediaStreamRendererFactory).
 //
 // This class uses AudioDeviceFactory to create media::AudioRendererSink and
 // owns/manages their lifecycles.  Output devices are automatically re-created
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
index 87dedff6..4aaf66ad 100644
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
@@ -35,7 +35,7 @@
 #include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/renderer/modules/mediastream/media_stream_local_frame_wrapper.h"
-#include "third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.h"
+#include "third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h"
 #include "third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
@@ -319,7 +319,7 @@
       paused_(true),
       video_transformation_(media::kNoTransformation),
       media_log_(std::move(media_log)),
-      renderer_factory_(std::make_unique<MediaStreamRendererFactoryImpl>()),
+      renderer_factory_(std::make_unique<MediaStreamRendererFactory>()),
       main_render_task_runner_(std::move(main_render_task_runner)),
       io_task_runner_(std::move(io_task_runner)),
       compositor_task_runner_(std::move(compositor_task_runner)),
@@ -1319,7 +1319,7 @@
 }
 
 void WebMediaPlayerMS::SetMediaStreamRendererFactoryForTesting(
-    std::unique_ptr<WebMediaStreamRendererFactory> renderer_factory) {
+    std::unique_ptr<MediaStreamRendererFactory> renderer_factory) {
   renderer_factory_ = std::move(renderer_factory);
 }
 
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
index 348e8dc..04e5f7f 100644
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc
@@ -27,9 +27,9 @@
 #include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/public/platform/web_media_player_client.h"
 #include "third_party/blink/public/platform/web_media_player_source.h"
-#include "third_party/blink/public/web/modules/mediastream/web_media_stream_renderer_factory.h"
 #include "third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h"
 #include "third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -440,7 +440,7 @@
 
 // The class is used to generate a MockVideoProvider in
 // WebMediaPlayerMS::load().
-class MockRenderFactory : public WebMediaStreamRendererFactory {
+class MockRenderFactory : public MediaStreamRendererFactory {
  public:
   MockRenderFactory(
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
@@ -690,7 +690,7 @@
                 WTF::Unretained(this)),
       std::move(submitter_), surface_layer_mode);
   player_->SetMediaStreamRendererFactoryForTesting(
-      std::unique_ptr<WebMediaStreamRendererFactory>(render_factory_));
+      std::unique_ptr<MediaStreamRendererFactory>(render_factory_));
 }
 
 MockMediaStreamVideoRenderer* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
diff --git a/third_party/blink/renderer/modules/webaudio/cpu/x86/oscillator_kernel_sse2.cc b/third_party/blink/renderer/modules/webaudio/cpu/x86/oscillator_kernel_sse2.cc
index 627b8ec..b88e9bd 100644
--- a/third_party/blink/renderer/modules/webaudio/cpu/x86/oscillator_kernel_sse2.cc
+++ b/third_party/blink/renderer/modules/webaudio/cpu/x86/oscillator_kernel_sse2.cc
@@ -154,9 +154,9 @@
   return std::make_tuple(k, virtual_read_index);
 }
 
-static __m128 WrapVirtualIndexVectorPd(__m128d x,
-                                       __m128d wave_size,
-                                       __m128d inv_wave_size) {
+static __m128d WrapVirtualIndexVectorPd(__m128d x,
+                                        __m128d wave_size,
+                                        __m128d inv_wave_size) {
   // Wrap the virtual index |x| to the range 0 to wave_size - 1.  This is done
   // by computing x - floor(x/wave_size)*wave_size.
   //
@@ -174,7 +174,7 @@
   // cmplt(a,b) returns 0xffffffffffffffff (-1) if a < b and 0 if not.  So cmp
   // is -1 or 0 depending on whether r < f, which is what we need to compute
   // floor(r).
-  __m128d cmp = _mm_cmplt_pd(r, _mm_cvtepi32_pd(f));
+  __m128i cmp = reinterpret_cast<__m128i>(_mm_cmplt_pd(r, _mm_cvtepi32_pd(f)));
 
   // Take the low 32 bits of each 64-bit result and move them into the two
   // lowest 32-bit fields.
@@ -226,8 +226,9 @@
 
   // Convert the virtual read index (parts) to an integer, and carefully
   // merge them into one vector.
-  const __m128i v_read0 = _mm_movelh_ps(_mm_cvttpd_epi32(v_read_index_lo),
-                                        _mm_cvttpd_epi32(v_read_index_hi));
+  const __m128i v_read0 = reinterpret_cast<__m128i>(_mm_movelh_ps(
+      reinterpret_cast<__m128>(_mm_cvttpd_epi32(v_read_index_lo)),
+      reinterpret_cast<__m128>(_mm_cvttpd_epi32(v_read_index_hi))));
 
   // Get index to next element being sure to wrap the index around if needed.
   const __m128i v_read1 =
diff --git a/third_party/blink/renderer/modules/webaudio/periodic_wave.cc b/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
index c8bee655..610cf1a 100644
--- a/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
+++ b/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
@@ -208,11 +208,12 @@
   // Negative frequencies are allowed, in which case we alias to the positive
   // frequency.  SSE2 doesn't have an fabs instruction, so just remove the sign
   // bit of the float numbers, effecitvely taking the absolute value.
-  const __m128 frequency = _mm_and_ps(_mm_loadu_ps(fundamental_frequency),
-                                      _mm_set1_epi32(0x7fffffff));
+  const __m128 frequency =
+      _mm_and_ps(_mm_loadu_ps(fundamental_frequency),
+                 reinterpret_cast<__m128>(_mm_set1_epi32(0x7fffffff)));
 
   // pos = 0xffffffff if freq > 0; otherwise 0
-  const __m128i pos = _mm_cmpgt_ps(frequency, _mm_set1_ps(0));
+  const __m128 pos = _mm_cmpgt_ps(frequency, _mm_set1_ps(0));
 
   // Calculate the pitch range.
   __m128 v_ratio =
diff --git a/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc b/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc
index ba052c6..8210e716 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.cc
@@ -9,13 +9,10 @@
 
 namespace blink {
 
-ChunkToLayerMapper::ChunkToLayerMapper(
-    const PropertyTreeState& layer_state,
-    const gfx::Vector2dF& layer_offset,
-    const FloatSize& visual_rect_subpixel_offset)
+ChunkToLayerMapper::ChunkToLayerMapper(const PropertyTreeState& layer_state,
+                                       const gfx::Vector2dF& layer_offset)
     : layer_state_(layer_state),
       layer_offset_(layer_offset),
-      visual_rect_subpixel_offset_(visual_rect_subpixel_offset),
       chunk_state_(layer_state_),
       translation_2d_or_matrix_(
           FloatSize(-layer_offset.x(), -layer_offset.y())) {}
@@ -86,7 +83,6 @@
   IntRect result;
   if (!mapped_rect.IsEmpty()) {
     InflateForRasterEffectOutset(mapped_rect);
-    AdjustVisualRectBySubpixelOffset(mapped_rect);
     result = EnclosingIntRect(mapped_rect);
   }
 #if DCHECK_IS_ON()
@@ -113,20 +109,9 @@
 
   visual_rect.Rect().Move(-layer_offset_.x(), -layer_offset_.y());
   InflateForRasterEffectOutset(visual_rect.Rect());
-  AdjustVisualRectBySubpixelOffset(visual_rect.Rect());
   return EnclosingIntRect(visual_rect.Rect());
 }
 
-void ChunkToLayerMapper::AdjustVisualRectBySubpixelOffset(
-    FloatRect& rect) const {
-  // Add back the layer's subpixel accumulation that was excluded from the
-  // visual rect by
-  // PaintInvalidator::ExcludeCompositedLayerSubpixelAccumulation().
-  // The condition below should be kept consistent with that function.
-  if (&chunk_state_.Transform() == &layer_state_.Transform())
-    rect.Move(visual_rect_subpixel_offset_);
-}
-
 void ChunkToLayerMapper::InflateForRasterEffectOutset(FloatRect& rect) const {
   if (raster_effect_outset_ == RasterEffectOutset::kHalfPixel)
     rect.Inflate(0.5);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h b/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h
index 28be439..8578523 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h
@@ -22,10 +22,8 @@
   DISALLOW_NEW();
 
  public:
-  ChunkToLayerMapper(
-      const PropertyTreeState& layer_state,
-      const gfx::Vector2dF& layer_offset,
-      const FloatSize& visual_rect_subpixel_offset = FloatSize());
+  ChunkToLayerMapper(const PropertyTreeState& layer_state,
+                     const gfx::Vector2dF& layer_offset);
 
   // This class can map from multiple chunks. Before mapping from a chunk, this
   // method must be called to prepare for the chunk.
@@ -46,12 +44,10 @@
   friend class ChunkToLayerMapperTest;
 
   IntRect MapUsingGeometryMapper(const IntRect&) const;
-  void AdjustVisualRectBySubpixelOffset(FloatRect&) const;
   void InflateForRasterEffectOutset(FloatRect&) const;
 
   const PropertyTreeState layer_state_;
   const gfx::Vector2dF layer_offset_;
-  const FloatSize visual_rect_subpixel_offset_;
 
   // The following fields are chunk-specific which are updated in
   // SwitchToChunk().
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index b87cba27..744d1f6 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -30,16 +30,13 @@
  public:
   ConversionContext(const PropertyTreeState& layer_state,
                     const gfx::Vector2dF& layer_offset,
-                    const FloatSize& visual_rect_subpixel_offset,
                     cc::DisplayItemList& cc_list)
       : layer_state_(layer_state),
         layer_offset_(layer_offset),
         current_transform_(&layer_state.Transform()),
         current_clip_(&layer_state.Clip()),
         current_effect_(&layer_state.Effect()),
-        chunk_to_layer_mapper_(layer_state_,
-                               layer_offset_,
-                               visual_rect_subpixel_offset),
+        chunk_to_layer_mapper_(layer_state_, layer_offset_),
         cc_list_(cc_list) {}
   ~ConversionContext();
 
@@ -759,11 +756,9 @@
     const PaintChunkSubset& paint_chunks,
     const PropertyTreeState& layer_state,
     const gfx::Vector2dF& layer_offset,
-    const FloatSize& visual_rect_subpixel_offset,
     const DisplayItemList& display_items,
     cc::DisplayItemList& cc_list) {
-  ConversionContext(layer_state, layer_offset, visual_rect_subpixel_offset,
-                    cc_list)
+  ConversionContext(layer_state, layer_offset, cc_list)
       .Convert(paint_chunks, display_items);
 }
 
@@ -775,8 +770,7 @@
     cc::DisplayItemList::UsageHint hint,
     RasterUnderInvalidationCheckingParams* under_invalidation_checking_params) {
   auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(hint);
-  ConvertInto(paint_chunks, layer_state, layer_offset, FloatSize(),
-              display_items, *cc_list);
+  ConvertInto(paint_chunks, layer_state, layer_offset, display_items, *cc_list);
 
   if (under_invalidation_checking_params) {
     auto& params = *under_invalidation_checking_params;
@@ -786,8 +780,8 @@
     // use cc_list because it is not finalized yet.
     auto list_clone = base::MakeRefCounted<cc::DisplayItemList>(
         cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer);
-    ConvertInto(paint_chunks, layer_state, layer_offset, FloatSize(),
-                display_items, *list_clone);
+    ConvertInto(paint_chunks, layer_state, layer_offset, display_items,
+                *list_clone);
     recorder.getRecordingCanvas()->drawPicture(list_clone->ReleaseAsRecord());
     params.tracking.CheckUnderInvalidations(params.debug_name,
                                             recorder.finishRecordingAsPicture(),
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
index 36abf87..738d36a8 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
@@ -25,7 +25,6 @@
 
 class DisplayItemList;
 class PaintChunkSubset;
-class FloatSize;
 class PropertyTreeState;
 class RasterInvalidationTracking;
 
@@ -61,7 +60,6 @@
   static void ConvertInto(const PaintChunkSubset&,
                           const PropertyTreeState& layer_state,
                           const gfx::Vector2dF& layer_offset,
-                          const FloatSize& visual_rect_subpixel_offset,
                           const DisplayItemList&,
                           cc::DisplayItemList&);
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
index 609d7715..4662c3e 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -590,7 +590,7 @@
       cc::DisplayItemList::kTopLevelDisplayItemList);
   PaintChunksToCcLayer::ConvertInto(
       chunks.chunks, PropertyTreeState(*layer_transform, c0(), e0()),
-      gfx::Vector2dF(100, 200), FloatSize(), chunks.items, *cc_list);
+      gfx::Vector2dF(100, 200), chunks.items, *cc_list);
   EXPECT_EQ(gfx::Rect(-50, -100, 100, 100), cc_list->VisualRectForTesting(4));
 
   EXPECT_THAT(*cc_list->ReleaseAsRecord(),
@@ -612,8 +612,7 @@
   auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
       cc::DisplayItemList::kTopLevelDisplayItemList);
   PaintChunksToCcLayer::ConvertInto(chunks.chunks, PropertyTreeState::Root(),
-                                    gfx::Vector2dF(), FloatSize(), chunks.items,
-                                    *cc_list);
+                                    gfx::Vector2dF(), chunks.items, *cc_list);
 
   EXPECT_THAT(
       *cc_list->ReleaseAsRecord(),
@@ -1333,8 +1332,8 @@
   auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
       cc::DisplayItemList::kTopLevelDisplayItemList);
   PaintChunksToCcLayer::ConvertInto(chunks.chunks, PropertyTreeState::Root(),
-                                    gfx::Vector2dF(5, 10), FloatSize(),
-                                    chunks.items, *cc_list);
+                                    gfx::Vector2dF(5, 10), chunks.items,
+                                    *cc_list);
   ASSERT_EQ(5u, cc_list->TotalOpCount());
   // (16 32) is (11, 22) + layer_offset.
   gfx::Rect expected_visual_rect(6, 12, 33, 44);
@@ -1367,8 +1366,8 @@
   auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
       cc::DisplayItemList::kTopLevelDisplayItemList);
   PaintChunksToCcLayer::ConvertInto(chunks.chunks, PropertyTreeState::Root(),
-                                    gfx::Vector2dF(5, 10), FloatSize(),
-                                    chunks.items, *cc_list);
+                                    gfx::Vector2dF(5, 10), chunks.items,
+                                    *cc_list);
   ASSERT_EQ(7u, cc_list->TotalOpCount());
   // This is the visual rect for all filter related paint operations, which is
   // the union of the draw record and reference box of the filter in the layer's
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index e911c04..d99bc8f 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -322,7 +322,7 @@
     EnsureRasterInvalidator().Generate(
         raster_invalidation_function_,
         GetPaintController().GetPaintArtifactShared(), layer_bounds,
-        layer_state_->state.Unalias(), VisualRectSubpixelOffset(), this);
+        layer_state_->state.Unalias(), this);
 
     if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
         PaintsContentOrHitTest()) {
@@ -749,7 +749,6 @@
   PaintChunksToCcLayer::ConvertInto(
       GetPaintController().PaintChunks(), layer_state_->state.Unalias(),
       gfx::Vector2dF(layer_state_->offset.X(), layer_state_->offset.Y()),
-      VisualRectSubpixelOffset(),
       paint_controller.GetPaintArtifact().GetDisplayItemList(), *display_list);
 
   PaintController::ClearFlagsForBenchmark();
@@ -766,13 +765,4 @@
   return result;
 }
 
-// Subpixel offset for visual rects which excluded composited layer's subpixel
-// accumulation during paint invalidation.
-// See PaintInvalidator::ExcludeCompositedLayerSubpixelAccumulation().
-FloatSize GraphicsLayer::VisualRectSubpixelOffset() const {
-  if (GetCompositingReasons() & CompositingReason::kComboAllDirectReasons)
-    return FloatSize(client_.SubpixelAccumulation());
-  return FloatSize();
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index f3f43b4d..d8b1c0d 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -276,8 +276,6 @@
   RasterInvalidator& EnsureRasterInvalidator();
   void SetNeedsDisplayInRect(const IntRect&);
 
-  FloatSize VisualRectSubpixelOffset() const;
-
   GraphicsLayerClient& client_;
 
   // Offset from the owning layoutObject
diff --git a/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc b/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
index 54f8b52..0ffab039 100644
--- a/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
@@ -175,10 +175,8 @@
     const PaintArtifact& new_paint_artifact,
     const PaintChunkSubset& new_chunks,
     const PropertyTreeState& layer_state,
-    const FloatSize& visual_rect_subpixel_offset,
     Vector<PaintChunkInfo>& new_chunks_info) {
-  ChunkToLayerMapper mapper(layer_state, layer_bounds_.OffsetFromOrigin(),
-                            visual_rect_subpixel_offset);
+  ChunkToLayerMapper mapper(layer_state, layer_bounds_.OffsetFromOrigin());
   Vector<bool> old_chunks_matched;
   old_chunks_matched.resize(old_paint_chunks_info_.size());
   wtf_size_t old_index = 0;
@@ -318,11 +316,10 @@
     scoped_refptr<const PaintArtifact> new_paint_artifact,
     const gfx::Rect& layer_bounds,
     const PropertyTreeState& layer_state,
-    const FloatSize& visual_rect_subpixel_offset,
     const DisplayItemClient* layer_client) {
   Generate(raster_invalidation_function, new_paint_artifact,
            new_paint_artifact->PaintChunks(), layer_bounds, layer_state,
-           visual_rect_subpixel_offset, layer_client);
+           layer_client);
 }
 
 void RasterInvalidator::Generate(
@@ -331,7 +328,6 @@
     const PaintChunkSubset& paint_chunks,
     const gfx::Rect& layer_bounds,
     const PropertyTreeState& layer_state,
-    const FloatSize& visual_rect_subpixel_offset,
     const DisplayItemClient* layer_client) {
   if (RasterInvalidationTracking::ShouldAlwaysTrack())
     EnsureTracking();
@@ -346,8 +342,7 @@
     // No raster invalidation is needed if either the old bounds or the new
     // bounds is empty, but we still need to update new_chunks_info for the
     // next cycle.
-    ChunkToLayerMapper mapper(layer_state, layer_bounds.OffsetFromOrigin(),
-                              visual_rect_subpixel_offset);
+    ChunkToLayerMapper mapper(layer_state, layer_bounds.OffsetFromOrigin());
     for (auto it = paint_chunks.begin(); it != paint_chunks.end(); ++it) {
       if (ShouldSkipForRasterInvalidation(*new_paint_artifact, *it))
         continue;
@@ -363,7 +358,7 @@
   } else {
     GenerateRasterInvalidations(raster_invalidation_function,
                                 *new_paint_artifact, paint_chunks, layer_state,
-                                visual_rect_subpixel_offset, new_chunks_info);
+                                new_chunks_info);
   }
 
   if (tracking_info_)
diff --git a/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h b/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
index 35b7fab..2aa33f3 100644
--- a/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
+++ b/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
@@ -42,7 +42,6 @@
                 scoped_refptr<const PaintArtifact>,
                 const gfx::Rect& layer_bounds,
                 const PropertyTreeState& layer_state,
-                const FloatSize& visual_rect_subpixel_offset = FloatSize(),
                 const DisplayItemClient* layer_client = nullptr);
 
   // Generate raster invalidations for a subset of the paint chunks in the
@@ -52,7 +51,6 @@
                 const PaintChunkSubset&,
                 const gfx::Rect& layer_bounds,
                 const PropertyTreeState& layer_state,
-                const FloatSize& visual_rect_subpixel_offset = FloatSize(),
                 const DisplayItemClient* layer_client = nullptr);
 
   const gfx::Rect& LayerBounds() const { return layer_bounds_; }
@@ -99,7 +97,6 @@
                                    const PaintArtifact&,
                                    const PaintChunkSubset&,
                                    const PropertyTreeState& layer_state,
-                                   const FloatSize& visual_rect_subpixel_offset,
                                    Vector<PaintChunkInfo>& new_chunks_info);
 
   ALWAYS_INLINE const PaintChunk& GetOldChunk(wtf_size_t index) const;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 8ac0122..b412d47a 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2689,6 +2689,136 @@
 crbug.com/1105958 external/wpt/payment-request/payment-is-showing.https.html [ Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac10.10 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win10 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win7 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.10 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win10 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win7 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] virtual/cors/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win10 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win7 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win10 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win7 ] virtual/cors/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win10 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win7 ] virtual/cors/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.13 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.11 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win10 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win7 ] external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Linux ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cache-storage-eager-reading/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win10 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win7 ] virtual/cache-storage-sequence/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.13 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.14 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Win10 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win7 ] external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.11 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.12 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Linux ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.13 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Win ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
+crbug.com/626703 [ Retina ] virtual/omt-worker-fetch/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html [ Failure Timeout ]
 crbug.com/626703 [ Linux ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
 crbug.com/626703 [ Mac ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
 crbug.com/626703 [ Win ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 79dc635..e2d8a5c0 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -84564,6 +84564,45 @@
         {}
        ]
       ],
+      "abspos-009.tentative.html": [
+       "0e71de200d5736cf047498e81f9f57bc5ce88d4b",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "abspos-010.tentative.html": [
+       "1d7ddec7f5e0add7c81c9e087ca0820432bb93d3",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "abspos-011.tentative.html": [
+       "01fac9dae156ca1f5b1e8b629deb97ecf9a10ca4",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "auto-margins-001.tentative.html": [
        "9e89ab6ca7f5220ea030aa537bcb3b64f156043d",
        [
@@ -199940,20 +199979,12 @@
     ],
     "api": {
      "abort": {
-      "general.any-expected.txt": [
-       "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f",
-       []
-      ],
       "general.any.serviceworker-expected.txt": [
-       "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f",
+       "5392aa4db3549a33abfded207bc95b7699cee200",
        []
       ],
-      "general.any.sharedworker-expected.txt": [
-       "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f",
-       []
-      ],
-      "general.any.worker-expected.txt": [
-       "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f",
+      "keepalive-expected.txt": [
+       "af3cbab5e8e828a79d36ec52ce773cd1e0da39d6",
        []
       ]
      },
@@ -200291,7 +200322,7 @@
        []
       ],
       "infinite-slow-response.py": [
-       "fa2c482ec19d94336f729cbd52673820873d4268",
+       "a26cd8064c88531e6877d2561cd16df964eb7f6e",
        []
       ],
       "inspect-headers.py": [
@@ -200327,11 +200358,11 @@
        []
       ],
       "stash-put.py": [
-       "36527b98b71785809cd6a490196dd9112fef9181",
+       "3af7d9199ace9fd0a4c4f840e14fbb70d7bc79f8",
        []
       ],
       "stash-take.py": [
-       "fcaf96c96a6411f5391276e984aaa226c8cb15b6",
+       "e6db80dd86df1e5a80e177b78bd40a59234885b0",
        []
       ],
       "status.py": [
@@ -211234,7 +211265,7 @@
         []
        ],
        "pitch-detector.js": [
-        "375fef77c02ab12144978eaf7dc7555ea7ebade6",
+        "78f22ccd85760255056f1114cfb9ba1c25fcc60e",
         []
        ],
        "playing-the-media-resource": {
@@ -211872,7 +211903,7 @@
         []
        ],
        "iframe-loading-lazy-expected.txt": [
-        "885afb61c974b1572fc1912b1d16d536b0f07245",
+        "fb8804941ba81b386e252e6f31002c5005f3b8fc",
         []
        ],
        "iframe-loading-lazy-load-event-expected.txt": [
@@ -216653,7 +216684,7 @@
      []
     ],
     "trusted-types.tentative.idl": [
-     "f2318d685676291a5ec85a1a0c3c408fa1a7f079",
+     "4e469c19b823bf3d452f480e086474e49741964a",
      []
     ],
     "ua-client-hints.idl": [
@@ -222714,7 +222745,7 @@
       []
      ],
      "mock-screenenumeration.js": [
-      "5a2d7b18d28229d9e0e3e53a22006a082de25dea",
+      "2e41f59ea809b6434d9363228b162dbcf3538f61",
       []
      ],
      "mock-screenenumeration.js.header": [
@@ -223003,7 +223034,7 @@
    },
    "screen_enumeration": {
     "README.md": [
-     "e3de83d0a8983b2131327556ff5acb011bcbf7e5",
+     "42a5ebfc5169f43fa9289e85fed4d640071fde3d",
      []
     ],
     "resources": {
@@ -233976,7 +234007,7 @@
       []
      ],
      "run.py": [
-      "95d9369f2a888657c23315d8d97b9eb636e3db96",
+      "e977b9a0d36ee4f05072b4ff6554bd8ddb85d09e",
       []
      ],
      "testfiles.py": [
@@ -234557,7 +234588,7 @@
        []
       ],
       "response.py": [
-       "b24f0cdf476850a10cdbe94bb857fc61ce32bcf8",
+       "895f174d5f057afdec7ca6fc7388a39263fea874",
        []
       ],
       "router.py": [
@@ -235535,11 +235566,11 @@
      []
     ],
     "url-setters-stripping.any-expected.txt": [
-     "c29cdee3a15173ad2a03bd8769dba39d57668d51",
+     "392c091d2ff9f6a0ed2622f1436d2e312491e5ce",
      []
     ],
     "url-setters-stripping.any.worker-expected.txt": [
-     "c29cdee3a15173ad2a03bd8769dba39d57668d51",
+     "392c091d2ff9f6a0ed2622f1436d2e312491e5ce",
      []
     ]
    },
@@ -287129,7 +287160,7 @@
       ]
      },
      "appearance-cssom-001.html": [
-      "49769b359a53cf54bf232e42d567f88513abf853",
+      "2f0644093ea7b7d99581f2fae13d2203b961adf0",
       [
        null,
        {}
@@ -339793,7 +339824,7 @@
         ]
        ],
        "preserves-pitch.html": [
-        "dad5f94e07be59f05804a7e29e0978cc4e89b2b8",
+        "1cf6c7639036edbc53c70ee71dc99edc6e224d58",
         [
          null,
          {
@@ -341656,7 +341687,7 @@
         ]
        ],
        "iframe-loading-lazy.html": [
-        "51b442695e01e9496ee4f5754023f722e6636f36",
+        "336703ebc47d7c78e7f367969977edd6cfafc26c",
         [
          null,
          {}
@@ -376811,7 +376842,7 @@
    },
    "screen_enumeration": {
     "getScreens.tentative.https.window.js": [
-     "f496282b01620f8b1d2d10c11e961f6fbb9dc56a",
+     "ad982b219cbe2baa540e37f27e4096d274ac09a2",
      [
       "screen_enumeration/getScreens.tentative.https.window.html",
       {
@@ -376833,7 +376864,36 @@
      ]
     ],
     "getScreens.values.https.html": [
-     "3b8060786e13fc1c11f9b54b4c3e927ecab1e43b",
+     "881396adbc3befefb39b55020d8f798379bfa648",
+     [
+      null,
+      {}
+     ]
+    ],
+    "isMultiScreen.tentative.https.window.js": [
+     "515731cc04fc7b0026f5972d9a5b96e649d8bc9e",
+     [
+      "screen_enumeration/isMultiScreen.tentative.https.window.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window"
+        ],
+        [
+         "script",
+         "/resources/testdriver.js"
+        ],
+        [
+         "script",
+         "/resources/testdriver-vendor.js"
+        ]
+       ]
+      }
+     ]
+    ],
+    "isMultiScreen.values.https.html": [
+     "5146803ea9c20c5f8ae43cf385895a95fc361747",
      [
       null,
       {}
@@ -389802,6 +389862,13 @@
       {}
      ]
     ],
+    "TrustedTypePolicyFactory-blocking.html": [
+     "6ae71b69880a0313a549b586a04fa38b4be466e2",
+     [
+      null,
+      {}
+     ]
+    ],
     "TrustedTypePolicyFactory-constants.tentative.html": [
      "551084ca4b6e001ce49213a3d12491a4aedaf8f4",
      [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html
index 49769b3..2f06440 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html
@@ -24,6 +24,7 @@
                   "textarea",
                   "textfield",
                  ];
+  const initial_appearance = getComputedStyle(button).appearance;
   function assert_style_for_prop(style, prop, value) {
     if (prop === '-webkit-appearance') {
       assert_equals(style.WebkitAppearance, value, 'style.WebkitAppearance (uppercase W)');
@@ -198,7 +199,7 @@
         button.style.setProperty(prop, invalidValue);
         assert_style_for_prop(button.style, prop, "");
         const style = getComputedStyle(button);
-        assert_style_for_prop(style, prop, "button");
+        assert_style_for_prop(style, prop, initial_appearance);
       }, `${prop}: ${invalidValue} (invalid)`);
     }
   }
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
index 99afa96..5392aa4 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -34,15 +34,15 @@
 PASS Already aborted signal does not make request
 PASS Already aborted signal can be used for many fetches
 PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
-PASS Underlying connection is closed when aborting after receiving response
-PASS Underlying connection is closed when aborting after receiving response - no-cors
-PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer()
-PASS Fetch aborted & connection closed when aborted after calling response.blob()
-PASS Fetch aborted & connection closed when aborted after calling response.formData()
-PASS Fetch aborted & connection closed when aborted after calling response.json()
-PASS Fetch aborted & connection closed when aborted after calling response.text()
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
 PASS Stream errors once aborted. Underlying connection closed.
-PASS Stream errors once aborted, after reading. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
 PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
 FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
 PASS Signal state is cloned
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/keepalive-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/abort/keepalive-expected.txt
new file mode 100644
index 0000000..af3cbab
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/abort/keepalive-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL aborting a keepalive fetch should work assert_equals: connection should be open expected "open" but got "closed"
+PASS aborting a detached keepalive fetch should not do anything
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/infinite-slow-response.py b/third_party/blink/web_tests/external/wpt/fetch/api/resources/infinite-slow-response.py
index fa2c482..a26cd80 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/infinite-slow-response.py
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/infinite-slow-response.py
@@ -2,7 +2,7 @@
 
 
 def url_dir(request):
-    return '/'.join(request.url_parts.path.split('/')[:-1]) + '/'
+    return u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
 
 
 def stash_write(request, key, value):
@@ -12,24 +12,23 @@
 
 
 def main(request, response):
-    stateKey = request.GET.first("stateKey", "")
-    abortKey = request.GET.first("abortKey", "")
+    stateKey = request.GET.first(b"stateKey", b"")
+    abortKey = request.GET.first(b"abortKey", b"")
 
     if stateKey:
         stash_write(request, stateKey, 'open')
 
-    response.headers.set("Content-type", "text/plain")
+    response.headers.set(b"Content-type", b"text/plain")
     response.write_status_headers()
 
     # Writing an initial 2k so browsers realise it's there. *shrug*
-    response.writer.write("." * 2048)
+    response.writer.write(b"." * 2048)
 
     while True:
-        if not response.writer.flush():
+        if not response.writer.write(b"."):
             break
         if abortKey and request.server.stash.take(abortKey, url_dir(request)):
             break
-        response.writer.write(".")
         time.sleep(0.01)
 
     if stateKey:
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py b/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py
index 36527b98..3af7d91 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-put.py
@@ -1,14 +1,14 @@
 def main(request, response):
-    if request.method == 'OPTIONS':
+    if request.method == u'OPTIONS':
         # CORS preflight
-        response.headers.set('Access-Control-Allow-Origin', '*')
-        response.headers.set('Access-Control-Allow-Methods', '*')
-        response.headers.set('Access-Control-Allow-Headers', '*')
+        response.headers.set(b'Access-Control-Allow-Origin', b'*')
+        response.headers.set(b'Access-Control-Allow-Methods', b'*')
+        response.headers.set(b'Access-Control-Allow-Headers', b'*')
         return 'done'
 
-    url_dir = '/'.join(request.url_parts.path.split('/')[:-1]) + '/'
-    key = request.GET.first("key")
-    value = request.GET.first("value")
+    url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
+    key = request.GET.first(b"key")
+    value = request.GET.first(b"value")
     request.server.stash.put(key, value, url_dir)
-    response.headers.set('Access-Control-Allow-Origin', '*')
+    response.headers.set(b'Access-Control-Allow-Origin', b'*')
     return "done"
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-take.py b/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-take.py
index fcaf96c..e6db80d 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-take.py
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/stash-take.py
@@ -3,7 +3,7 @@
 
 @json_handler
 def main(request, response):
-    dir = '/'.join(request.url_parts.path.split('/')[:-1]) + '/'
-    key = request.GET.first("key")
-    response.headers.set('Access-Control-Allow-Origin', '*')
+    dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
+    key = request.GET.first(b"key")
+    response.headers.set(b'Access-Control-Allow-Origin', b'*')
     return request.server.stash.take(key, dir)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
index 95d9369..e977b9a 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
@@ -309,8 +309,8 @@
             os.environ["ADB_PATH"] = adb_path
         adb_path = os.environ["ADB_PATH"]
 
-        device = mozdevice.ADBDevice(adb=adb_path,
-                                     device=kwargs["device_serial"])
+        device = mozdevice.ADBDeviceFactory(adb=adb_path,
+                                            device=kwargs["device_serial"])
 
         if install:
             device.uninstall_app(app)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py
index b24f0cd..895f174 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py
@@ -762,9 +762,10 @@
         self.content_written = True
         try:
             self._wfile.write(self.encode(data))
+            return True
         except socket.error:
             # This can happen if the socket got closed by the remote end
-            pass
+            return False
 
     def write_content_file(self, data):
         """Write a file-like object directly to the response in chunks.
diff --git a/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt b/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
index 1d53bec0..aee46ba 100644
--- a/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
@@ -11,8 +11,8 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [11, 0, 14, 12],
-        [9, 0, 14, 12]
+        [12, 0, 12, 12],
+        [10, 0, 12, 12]
       ],
       "transform": 1
     }
@@ -42,8 +42,8 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [11, 0, 14, 12],
-        [9, 0, 14, 12]
+        [11, 0, 13, 12],
+        [9, 0, 13, 12]
       ],
       "transform": 1
     }
@@ -73,8 +73,8 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [12, 0, 14, 12],
-        [10, 0, 14, 12]
+        [12, 0, 13, 12],
+        [10, 0, 13, 12]
       ],
       "transform": 1
     }
@@ -104,8 +104,8 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [11, 0, 14, 12],
-        [9, 0, 14, 12]
+        [12, 0, 13, 12],
+        [10, 0, 13, 12]
       ],
       "transform": 1
     }
@@ -135,8 +135,8 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [12, 0, 14, 12],
-        [10, 0, 14, 12]
+        [12, 0, 13, 12],
+        [10, 0, 13, 12]
       ],
       "transform": 1
     }
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt
new file mode 100644
index 0000000..f7ff4ab
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling background of LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "bounds": [784, 502],
+      "invalidations": [
+        [1, 317, 782, 54],
+        [1, 263, 782, 54],
+        [1, 426, 782, 53],
+        [1, 372, 782, 53],
+        [1, 209, 782, 53],
+        [1, 155, 782, 53],
+        [1, 101, 782, 53]
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.html b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.html
new file mode 100644
index 0000000..387c053
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<style>
+#container div {
+  height: 50px;
+  border: 1px solid black;
+  margin-top: 2px;
+}
+#container {
+  margin-top: 110px;
+}
+</style>
+<div id="container">
+<!-- The geometries below matches the imperfect subpixel painting after
+     the composited layers are moved in subpixels. -->
+  <div></div>
+  <div style="height: 51px"></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div style="height: 51px"></div>
+</div>
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt
new file mode 100644
index 0000000..39e2324
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt
@@ -0,0 +1,27 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling background of LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "bounds": [784, 378],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 110, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html
new file mode 100644
index 0000000..81b6b8e
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<style>
+div {
+  height: 50px;
+  border: 1px solid black;
+  margin-top: 2px;
+}
+#first {
+  background-color: yellow;
+  margin-top: 110px;
+}
+</style>
+<div id="first"></div>
+<!-- The geometries below matches the imperfect subpixel painting after
+     the composited layers are moved in subpixels. -->
+<div style="height: 51px"></div>
+<div style="margin-top: 1px"></div>
+<div style="margin-top: 3px"></div>
+<div></div>
+<div></div>
+<div style="height: 51px"></div>
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
index 275b45d9..c1b4181 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
@@ -7,7 +7,7 @@
       "backgroundColor": "#FFFFFF"
     },
     {
-      "name": "LayoutNGBlockFlow (relative positioned) DIV id='first'",
+      "name": "LayoutNGBlockFlow DIV id='first'",
       "bounds": [784, 53],
       "backgroundColor": "#FFFF00",
       "transform": 1
@@ -15,14 +15,34 @@
     {
       "name": "LayoutNGBlockFlow DIV",
       "bounds": [784, 53],
-      "backgroundColor": "#D3D3D3",
       "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow DIV",
+      "position": [0, -1],
       "bounds": [784, 53],
-      "backgroundColor": "#D3D3D3",
       "transform": 3
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "position": [0, -1],
+      "bounds": [784, 54],
+      "transform": 4
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 53],
+      "transform": 5
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 53],
+      "transform": 6
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 53],
+      "transform": 7
     }
   ],
   "transforms": [
@@ -41,7 +61,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [8, 162, 0, 1]
+        [8, 164, 0, 1]
       ]
     },
     {
@@ -50,7 +70,43 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [8, 214, 0, 1]
+        [8, 218, 0, 1]
+      ]
+    },
+    {
+      "id": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 273, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 327, 0, 1]
+      ]
+    },
+    {
+      "id": 6,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 381, 0, 1]
+      ]
+    },
+    {
+      "id": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 435, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt
index 82c7392..991945e 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt
@@ -4,7 +4,11 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#FFFFFF",
+      "invalidations": [
+        [85, 70, 91, 92],
+        [84, 70, 91, 92]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
index 8818f3e..59a3cab0 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
@@ -11,8 +11,8 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [11, 0, 14, 12],
-        [9, 0, 14, 12]
+        [12, 0, 12, 12],
+        [10, 0, 12, 12]
       ],
       "transform": 1
     }
@@ -42,8 +42,8 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [11, 0, 14, 12],
-        [9, 0, 14, 12]
+        [11, 0, 13, 12],
+        [9, 0, 13, 12]
       ],
       "transform": 1
     }
@@ -73,8 +73,8 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [12, 0, 14, 12],
-        [10, 0, 14, 12]
+        [12, 0, 13, 12],
+        [10, 0, 13, 12]
       ],
       "transform": 1
     }
@@ -104,8 +104,8 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [11, 0, 14, 12],
-        [9, 0, 14, 12]
+        [12, 0, 13, 12],
+        [10, 0, 13, 12]
       ],
       "transform": 1
     }
@@ -135,8 +135,8 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='container'",
       "bounds": [100, 50],
       "invalidations": [
-        [12, 0, 14, 12],
-        [10, 0, 14, 12]
+        [12, 0, 13, 12],
+        [10, 0, 13, 12]
       ],
       "transform": 1
     }
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt
new file mode 100644
index 0000000..c323c76
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container'",
+      "bounds": [784, 502],
+      "invalidations": [
+        [1, 317, 782, 54],
+        [1, 263, 782, 54],
+        [1, 426, 782, 53],
+        [1, 372, 782, 53],
+        [1, 209, 782, 53],
+        [1, 155, 782, 53],
+        [1, 101, 782, 53]
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt
new file mode 100644
index 0000000..aee7e0a
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt
@@ -0,0 +1,30 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container'",
+      "bounds": [784, 377],
+      "invalidations": [
+        [0, 0, 784, 377]
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 110, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
index 66cb826..281b277 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
@@ -7,7 +7,7 @@
       "backgroundColor": "#FFFFFF"
     },
     {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='first'",
+      "name": "LayoutBlockFlow DIV id='first'",
       "bounds": [784, 52],
       "contentsOpaque": true,
       "backgroundColor": "#FFFF00",
@@ -16,16 +16,32 @@
     {
       "name": "LayoutBlockFlow DIV",
       "bounds": [784, 52],
-      "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
       "transform": 2
     },
     {
       "name": "LayoutBlockFlow DIV",
-      "bounds": [784, 52],
-      "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
+      "bounds": [784, 53],
       "transform": 3
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 4
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 5
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 6
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 7
     }
   ],
   "transforms": [
@@ -44,7 +60,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [8, 162, 0, 1]
+        [8, 164, 0, 1]
       ]
     },
     {
@@ -53,7 +69,43 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [8, 214, 0, 1]
+        [8, 218, 0, 1]
+      ]
+    },
+    {
+      "id": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 273, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 327, 0, 1]
+      ]
+    },
+    {
+      "id": 6,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 381, 0, 1]
+      ]
+    },
+    {
+      "id": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 435, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.html
new file mode 100644
index 0000000..7d92db4
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<style>
+#container div {
+  height: 50px;
+  border: 1px solid black;
+  margin-top: 2px;
+}
+#container {
+  border: 1px solid green;
+  height: 500px;
+}
+#container #first {
+  margin-top: 100px;
+  background: yellow;
+}
+</style>
+<div id="container">
+  <div id="first"></div>
+  <div></div>
+  <div style="height: 51px"></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt
new file mode 100644
index 0000000..f931854
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "bounds": [784, 502],
+      "invalidations": [
+        [1, 317, 782, 54],
+        [1, 263, 782, 54],
+        [1, 426, 782, 53],
+        [1, 372, 782, 53],
+        [1, 209, 782, 53],
+        [1, 155, 782, 53],
+        [1, 101, 782, 53]
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels.html
new file mode 100644
index 0000000..5ad5dc149
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-contents-move-in-subpixels.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+#container div {
+  height: 50.2px;
+  border: 1px solid black;
+  margin-top: 2px;
+}
+#container {
+  will-change: transform;
+  border: 1px solid green;
+  height: 500px;
+}
+#container #first {
+  margin-top: 100.3px;
+  background: yellow;
+}
+</style>
+<div id="container">
+  <div id="first"></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
+<script src="../resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+  first.style.marginTop = '100.1px';
+}
+onload = runRepaintAndPixelTest;
+</script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.html
new file mode 100644
index 0000000..09a9ad1
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<style>
+#container div {
+  height: 50px;
+  border: 1px solid black;
+  margin-top: 2px;
+}
+#container {
+  margin-top: 110px;
+}
+</style>
+<div id="container">
+<!-- The geometries below matches the imperfect subpixel painting after
+     the composited layers are moved in subpixels. -->
+  <div></div>
+  <div style="height: 51px"></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <!-- The missing border-bottom is because of crbug.com/1102886 which we won't
+       fix in pre-CompositeAfterPaint. -->
+  <div style="height: 51px; border-bottom: none"></div>
+</div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt
new file mode 100644
index 0000000..fb297e1a
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents-expected.txt
@@ -0,0 +1,30 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "bounds": [784, 377],
+      "invalidations": [
+        [0, 0, 784, 377]
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 110, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents.html
new file mode 100644
index 0000000..468f296a
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layer-move-in-subpixels-contents.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<style>
+#container div {
+  height: 50.2px;
+  border: 1px solid black;
+  margin-top: 2px;
+}
+#container {
+  will-change: transform;
+  margin-top: 100.3px;
+}
+</style>
+<div id="container">
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
+<script src="../resources/text-based-repaint.js"></script>
+<script>
+// Disable under-invalidation checking which would force full layer
+// invalidation on subpixel accumulation change.
+if (window.internals)
+  internals.runtimeFlags.paintUnderInvalidationCheckingEnabled = false;
+function repaintTest() {
+  container.style.marginTop = '110.1px';
+}
+onload = runRepaintAndPixelTest;
+</script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html
index abe1134..4eab213 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.html
@@ -1,16 +1,23 @@
 <!DOCTYPE html>
 <style>
 div {
-  background-color: lightgray;
   height: 50px;
   border: 1px solid black;
+  margin-top: 2px;
 }
 #first {
   background-color: yellow;
-  position: relative;
   margin-top: 110px;
 }
 </style>
 <div id="first"></div>
+<!-- The geometries below matches the imperfect subpixel painting after
+     the composited layers are moved in subpixels. -->
+<!-- The missing border-bottom is because of crbug.com/1102886 which we won't
+     fix in pre-CompositeAfterPaint. -->
+<div style="height: 51px; border-bottom: none"></div>
+<div></div>
+<div style="margin-top: 3px"></div>
 <div></div>
 <div></div>
+<div style="height: 51px; border-bottom: none"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
index 247b010..a6e7de18 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels-expected.txt
@@ -7,7 +7,7 @@
       "backgroundColor": "#FFFFFF"
     },
     {
-      "name": "LayoutNGBlockFlow (relative positioned) DIV id='first'",
+      "name": "LayoutNGBlockFlow DIV id='first'",
       "bounds": [784, 52],
       "contentsOpaque": true,
       "backgroundColor": "#FFFF00",
@@ -16,16 +16,32 @@
     {
       "name": "LayoutNGBlockFlow DIV",
       "bounds": [784, 52],
-      "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
       "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "bounds": [784, 52],
-      "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
+      "bounds": [784, 53],
       "transform": 3
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 4
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 5
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 6
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [784, 52],
+      "transform": 7
     }
   ],
   "transforms": [
@@ -44,7 +60,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [8, 162, 0, 1]
+        [8, 164, 0, 1]
       ]
     },
     {
@@ -53,7 +69,43 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [8, 214, 0, 1]
+        [8, 218, 0, 1]
+      ]
+    },
+    {
+      "id": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 273, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 327, 0, 1]
+      ]
+    },
+    {
+      "id": 6,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 381, 0, 1]
+      ]
+    },
+    {
+      "id": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 435, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels.html
index baae828..1f66a18 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-layers-move-in-subpixels.html
@@ -2,19 +2,22 @@
 <style>
 div {
   will-change: transform;
-  background-color: lightgray;
-  height: 50px;
+  height: 50.2px;
   border: 1px solid black;
+  margin-top: 2px;
 }
 #first {
   background-color: yellow;
-  position: relative;
   margin-top: 100.3px;
 }
 </style>
 <div id="first"></div>
 <div></div>
 <div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
 <script src="../resources/text-based-repaint.js"></script>
 <script>
 // Disable under-invalidation checking which would force full layer
diff --git a/third_party/blink/web_tests/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt b/third_party/blink/web_tests/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt
index c543542..02a551d 100644
--- a/third_party/blink/web_tests/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/transform/invalidation-with-scale-transform-expected.txt
@@ -4,7 +4,11 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#FFFFFF",
+      "invalidations": [
+        [85, 70, 91, 92],
+        [84, 70, 91, 92]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any-expected.txt
rename to third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
rename to third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/api/abort/general.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..195db3494
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+PASS Underlying connection is closed when aborting after receiving response
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/win/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win7/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/win7/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/cors/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
new file mode 100644
index 0000000..5392aa4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+FAIL Stream errors once aborted, after reading. Underlying connection closed. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
new file mode 100644
index 0000000..743794e3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected (string) "open" but got (object) null
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/cors/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
new file mode 100644
index 0000000..47a8c8da
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+PASS Aborting rejects with AbortError
+PASS Aborting rejects with AbortError - no-cors
+PASS TypeError from request constructor takes priority - RequestInit's window is not null
+PASS TypeError from request constructor takes priority - Input URL is not valid
+PASS TypeError from request constructor takes priority - Input URL has credentials
+PASS TypeError from request constructor takes priority - RequestInit's mode is navigate
+PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is invalid
+PASS TypeError from request constructor takes priority - RequestInit's method is forbidden
+PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple
+PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors
+PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors
+PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value
+PASS TypeError from request constructor takes priority - Bad mode init parameter value
+PASS TypeError from request constructor takes priority - Bad credentials init parameter value
+PASS TypeError from request constructor takes priority - Bad cache init parameter value
+PASS TypeError from request constructor takes priority - Bad redirect init parameter value
+PASS Request objects have a signal property
+PASS Signal on request object
+PASS Signal on request object created from request object
+PASS Signal on request object created from request object, with signal on second request
+PASS Signal on request object created from request object, with signal on second request overriding another
+PASS Signal retained after unrelated properties are overridden by fetch
+PASS Signal removed by setting to null
+PASS Already aborted signal rejects immediately
+PASS Request is still 'used' if signal is aborted before fetching
+PASS response.arrayBuffer() rejects if already aborted
+PASS response.blob() rejects if already aborted
+PASS response.formData() rejects if already aborted
+PASS response.json() rejects if already aborted
+PASS response.text() rejects if already aborted
+PASS Already aborted signal does not make request
+PASS Already aborted signal can be used for many fetches
+PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
+FAIL Underlying connection is closed when aborting after receiving response assert_equals: Connection is open expected "open" but got "closed"
+FAIL Underlying connection is closed when aborting after receiving response - no-cors assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_equals: Connection is open expected "open" but got "closed"
+FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_equals: Connection is open expected "open" but got "closed"
+PASS Stream errors once aborted. Underlying connection closed.
+PASS Stream errors once aborted, after reading. Underlying connection closed.
+PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
+FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false
+PASS Signal state is cloned
+PASS Clone aborts with original controller
+Harness: the test ran to completion.
+
diff --git a/third_party/closure_compiler/externs/quick_unlock_private.js b/third_party/closure_compiler/externs/quick_unlock_private.js
index 48efff3..4cb0e28c 100644
--- a/third_party/closure_compiler/externs/quick_unlock_private.js
+++ b/third_party/closure_compiler/externs/quick_unlock_private.js
@@ -75,6 +75,25 @@
 chrome.quickUnlockPrivate.setLockScreenEnabled = function(token, enabled, onComplete) {};
 
 /**
+ * Sets PIN auto submit enabled state. NOTE: PIN auto submit state is reflected
+ * in the pin_unlock_autosubmit_enabled, which can be read but not written
+ * using the settings_private API (which also provides policy information). This
+ * API must be used to change the pref.
+ * @param {string} token The token returned by $(ref:getAuthToken).
+ * @param {string} pin The user's PIN for verification
+ * @param {boolean} enabled Whether to enable PIN auto submit
+ * @param {function(boolean): void=} onComplete
+ */
+chrome.quickUnlockPrivate.setPinAutosubmitEnabled =
+    function(token, pin, enabled, onComplete) {};
+
+/**
+ * Checks whether it is currently possible to authenticate using PIN.
+ * @param {function(boolean): void=} onComplete
+ */
+chrome.quickUnlockPrivate.canAuthenticatePin = function(onComplete) {};
+
+/**
  * Returns the set of quick unlock modes that are available for the user to use.
  * Some quick unlock modes may be disabled by policy.
  * @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>): void}
diff --git a/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js b/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js
index e8a060e..28cb543 100644
--- a/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js
+++ b/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js
@@ -36,6 +36,24 @@
   setLockScreenEnabled: assertNotReached,
 
   /**
+   * Sets PIN auto submit enabled state. NOTE: PIN auto submit state is reflected
+   * in the pin_unlock_autosubmit_enabled, which can be read but not written
+   * using the settings_private API (which also provides policy information). This
+   * API must be used to change the pref.
+   * @param {string} token The token returned by $(ref:getAuthToken).
+   * @param {string} pin The user's PIN for verification
+   * @param {boolean} enabled Whether to enable PIN auto submit
+   * @param {function(boolean): void=} onComplete
+   */
+  setPinAutosubmitEnabled: assertNotReached,
+
+  /**
+   * Checks whether it is currently possible to authenticate using PIN.
+   * @param {function(boolean): void=} onComplete
+   */
+  canAuthenticatePin: assertNotReached,
+
+  /**
    * Returns the set of quick unlock modes that are available for the user to
    * use. Some quick unlock modes may be disabled by policy.
    * @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void}
diff --git a/third_party/libavif/OWNERS b/third_party/libavif/OWNERS
index 5b8a6e87..593af015 100644
--- a/third_party/libavif/OWNERS
+++ b/third_party/libavif/OWNERS
@@ -1,3 +1,3 @@
-# COMPONENT: Internals>Media>Codecs
+# COMPONENT: Internals>Images>Codecs
 file://media/OWNERS
 wtc@google.com
diff --git a/third_party/win_build_output/mc/chrome/credential_provider/eventlog/MSG00409.bin b/third_party/win_build_output/mc/chrome/credential_provider/eventlog/MSG00409.bin
index 9b0312b..bf6b1caf 100644
--- a/third_party/win_build_output/mc/chrome/credential_provider/eventlog/MSG00409.bin
+++ b/third_party/win_build_output/mc/chrome/credential_provider/eventlog/MSG00409.bin
Binary files differ
diff --git a/third_party/win_build_output/mc/chrome/credential_provider/eventlog/gcp_eventlog_messages.h b/third_party/win_build_output/mc/chrome/credential_provider/eventlog/gcp_eventlog_messages.h
index 977a8fa7..1b73731 100644
--- a/third_party/win_build_output/mc/chrome/credential_provider/eventlog/gcp_eventlog_messages.h
+++ b/third_party/win_build_output/mc/chrome/credential_provider/eventlog/gcp_eventlog_messages.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.

+// 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.

 //

@@ -56,6 +56,15 @@
 #define GCPW_CATEGORY                    ((WORD)0x00000001L)

 

 //

+// MessageId: GCPW_EXTENSION_CATEGORY

+//

+// MessageText:

+//

+// GCPW Extension Events

+//

+#define GCPW_EXTENSION_CATEGORY          ((WORD)0x00000002L)

+

+//

 // MessageId: MSG_LOG_MESSAGE

 //

 // MessageText:

diff --git a/tools/android/dependency_analysis/js/src/graph_model.js b/tools/android/dependency_analysis/js/src/graph_model.js
index 4c6c673..b0ebe7c 100644
--- a/tools/android/dependency_analysis/js/src/graph_model.js
+++ b/tools/android/dependency_analysis/js/src/graph_model.js
@@ -80,11 +80,13 @@
 
 /** A node representing a Java class. */
 class ClassNode extends GraphNode {
-  constructor(id, displayName, packageName) {
+  constructor(id, displayName, packageName, buildTargets) {
     super(id, displayName);
 
     /** @public {string} */
     this.packageName = packageName;
+    /** @public {!Array<string>} */
+    this.buildTargets = buildTargets;
   }
 }
 
diff --git a/tools/android/dependency_analysis/js/src/process_graph_json.js b/tools/android/dependency_analysis/js/src/process_graph_json.js
index 65b9a7a..bcd4e854 100644
--- a/tools/android/dependency_analysis/js/src/process_graph_json.js
+++ b/tools/android/dependency_analysis/js/src/process_graph_json.js
@@ -60,7 +60,8 @@
  */
 function parseClassGraphModelFromJson(jsonGraph) {
   const makeClassNode = nodeData => new ClassNode(
-      nodeData.name, shortenClassName(nodeData.name), nodeData.meta.package);
+      nodeData.name, shortenClassName(nodeData.name), nodeData.meta.package,
+      nodeData.meta.build_targets);
   return parseGraphModelFromJson(jsonGraph, makeClassNode);
 }
 
diff --git a/tools/android/dependency_analysis/js/src/vue_components/class_details_panel.vue b/tools/android/dependency_analysis/js/src/vue_components/class_details_panel.vue
new file mode 100644
index 0000000..2a594e4
--- /dev/null
+++ b/tools/android/dependency_analysis/js/src/vue_components/class_details_panel.vue
@@ -0,0 +1,44 @@
+<!-- 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. -->
+
+<template>
+  <div
+      v-if="selectedClass !== null"
+      class="class-details-panel">
+    <LinkToGraph
+        :filter="[selectedClass.packageName]"
+        :graph-type="PagePathName.PACKAGE"
+        :text="'View ' + selectedClass.packageName"/>
+    <div v-if="selectedClass.buildTargets.length > 0">
+      <div>Class buildtarget(s):</div>
+      <ul>
+        <li
+            v-for="buildTarget in selectedClass.buildTargets"
+            :key="buildTarget">
+          {{ buildTarget }}
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script>
+import {PagePathName} from '../url_processor.js';
+
+import LinkToGraph from './link_to_graph.vue';
+
+const ClassDetailsPanel = {
+  components: {
+    LinkToGraph,
+  },
+  props: {
+    selectedClass: Object,
+  },
+  computed: {
+    PagePathName: () => PagePathName,
+  },
+};
+
+export default ClassDetailsPanel;
+</script>
\ No newline at end of file
diff --git a/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue b/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue
index c926572..299553df 100644
--- a/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue
+++ b/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue
@@ -28,13 +28,8 @@
             :selected-node-details-data="pageModel.selectedNodeDetailsData"
             @[CUSTOM_EVENTS.ADD_TO_FILTER_CLICKED]="addNodeToFilter"
             @[CUSTOM_EVENTS.REMOVE_FROM_FILTER_CLICKED]="removeNodeFromFilter"/>
-        <LinkToGraph
-            v-if="pageModel.selectedNodeDetailsData.selectedNode !== null"
-            :filter="
-              [pageModel.selectedNodeDetailsData.selectedNode.packageName]"
-            :graph-type="PagePathName.PACKAGE"
-            :text="'View ' +
-              pageModel.selectedNodeDetailsData.selectedNode.packageName"/>
+        <ClassDetailsPanel
+            :selected-class="pageModel.selectedNodeDetailsData.selectedNode"/>
       </div>
     </div>
     <PageUrlGenerator
@@ -51,6 +46,7 @@
 import {PageModel} from '../page_model.js';
 import {parseClassGraphModelFromJson} from '../process_graph_json.js';
 
+import ClassDetailsPanel from './class_details_panel.vue';
 import GraphFilterInput from './graph_filter_input.vue';
 import GraphFilterItems from './graph_filter_items.vue';
 import GraphInboundInput from './graph_inbound_input.vue';
@@ -62,6 +58,7 @@
 
 const ClassGraphPage = {
   components: {
+    ClassDetailsPanel,
     GraphFilterInput,
     GraphFilterItems,
     GraphInboundInput,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index fa76838..e1175df 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -6266,6 +6266,47 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="Extensions.ContextMenu.Hosts.LearnMoreClicked">
+  <owner>tjudkins@chromium.org</owner>
+  <owner>extensions-core@chromium.org</owner>
+  <description>
+    The user clicked the &quot;Learn more about site access&quot; option in the
+    runtime host permissions section of an extension's context menu. This is
+    recorded for both keyboard and mouse activations.
+  </description>
+</action>
+
+<action name="Extensions.ContextMenu.Hosts.OnAllSitesClicked">
+  <owner>tjudkins@chromium.org</owner>
+  <owner>extensions-core@chromium.org</owner>
+  <description>
+    The user clicked the &quot;On all sites&quot; option in the runtime host
+    permissions section of an extension's context menu. This is recorded for
+    both keyboard and mouse activations.
+  </description>
+</action>
+
+<action name="Extensions.ContextMenu.Hosts.OnClickClicked">
+  <owner>tjudkins@chromium.org</owner>
+  <owner>extensions-core@chromium.org</owner>
+  <description>
+    The user clicked the &quot;When you click the extension&quot; option in the
+    runtime host permissions section of an extension's context menu. This is
+    recorded for both keyboard and mouse activations.
+  </description>
+</action>
+
+<action name="Extensions.ContextMenu.Hosts.OnSiteClicked">
+  <owner>tjudkins@chromium.org</owner>
+  <owner>extensions-core@chromium.org</owner>
+  <description>
+    The user clicked the &quot;On {site}&quot; option in the runtime host
+    permissions section of an extension's context menu, where &quot;{site}&quot;
+    is the domain of the current page. This is recorded for both keyboard and
+    mouse activations.
+  </description>
+</action>
+
 <action name="Extensions.ExtensionDisabled">
   <owner>archanasimha@chromium.org</owner>
   <description>
@@ -6352,6 +6393,15 @@
   </description>
 </action>
 
+<action name="Extensions.Toolbar.MoreActionsButtonPressedFromMenu">
+  <owner>tjudkins@chromium.org</owner>
+  <owner>extensions-core@chromium.org</owner>
+  <description>
+    The user activated the more actions button for an extension in the
+    Extensions Menu. This is recorded for both keyboard and mouse activation.
+  </description>
+</action>
+
 <action name="Extensions.Toolbar.PinButtonPressed">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
@@ -18356,6 +18406,15 @@
   </description>
 </action>
 
+<action name="PaintPreview.Player.LongPress">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <owner>mahmoudi@chromium.org</owner>
+  <description>
+    Records when the user long presses on the paint preview player.
+  </description>
+</action>
+
 <action name="PaintPreview.Player.Scrolled">
   <owner>ckitagawa@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
@@ -18365,6 +18424,16 @@
   </description>
 </action>
 
+<action name="PaintPreview.Player.UnconsumedTap">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <owner>mahmoudi@chromium.org</owner>
+  <description>
+    Records when the user taps on an area in the paint preview player that is
+    not a link.
+  </description>
+</action>
+
 <action name="PaintPreview.Player.Zoomed">
   <owner>ckitagawa@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
@@ -20367,6 +20436,14 @@
   </description>
 </action>
 
+<action name="SharingHubAndroid.LinkToTextSelected">
+  <owner>gayane@chromium.org</owner>
+  <owner>src/components/send_tab_to_self/OWNERS</owner>
+  <description>
+    The &quot;Link to text&quot; option was selected in the sharing hub.
+  </description>
+</action>
+
 <action name="SharingHubAndroid.MoreSelected">
   <owner>kmilka@chromium.org</owner>
   <owner>src/components/send_tab_to_self/OWNERS</owner>
@@ -24553,6 +24630,9 @@
 </action>
 
 <action name="TabsSuggestions.Close.Accepted">
+  <obsolete>
+    This is renamed to TabSuggestions.Considered.Accepted.Closing on 07/2020.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>davidjm@chromium.org</owner>
   <description>
@@ -24562,6 +24642,9 @@
 </action>
 
 <action name="TabsSuggestions.Close.Dismissed">
+  <obsolete>
+    This is renamed to TabSuggestions.Considered.Dismissed.Closing on 07/2020.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>davidjm@chromium.org</owner>
   <description>
@@ -24571,6 +24654,7 @@
 </action>
 
 <action name="TabsSuggestions.Close.SuggestionsReview.Accepted">
+  <obsolete>This is removed as 07/2020.</obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>davidjm@chromium.org</owner>
   <description>
@@ -24580,6 +24664,9 @@
 </action>
 
 <action name="TabsSuggestions.Close.SuggestionsReview.Dismissed">
+  <obsolete>
+    This is renamed to TabsSuggestions.NotConsidered.Closing on 07/2020.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>davidjm@chromium.org</owner>
   <description>
@@ -24588,6 +24675,36 @@
   </description>
 </action>
 
+<action name="TabsSuggestions.Considered.Accepted">
+  <owner>yusufo@chromium.org</owner>
+  <owner>davidjm@chromium.org</owner>
+  <owner>meiliang@chromium.org</owner>
+  <description>
+    The tab suggestions were considered and accepted by the user (with some
+    possible editing).
+  </description>
+</action>
+
+<action name="TabsSuggestions.Considered.Dismissed">
+  <owner>yusufo@chromium.org</owner>
+  <owner>davidjm@chromium.org</owner>
+  <owner>meiliang@chromiu.org</owner>
+  <description>
+    The tab suggestions were considered and dismissed by the user (with some
+    possible editing).
+  </description>
+</action>
+
+<action name="TabsSuggestions.NotConsidered">
+  <owner>yusufo@chromium.org</owner>
+  <owner>davidjm@chromium.org</owner>
+  <owner>meiliang@chromium.org</owner>
+  <description>
+    The tab suggestions were not considered at all by the user by dismissing the
+    tab suggestion card indicating tab suggestions are available.
+  </description>
+</action>
+
 <action name="TabStrip">
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
@@ -26296,4 +26413,14 @@
   <affected-action name="TabGridDialog"/>
 </action-suffix>
 
+<action-suffix separator="." ordering="suffix">
+  <suffix name="Closing"
+      label="Users took action on the closing tabs suggestion."/>
+  <suffix name="Grouping"
+      label="Users took action on the grouping tabs suggestion."/>
+  <affected-action name="TabsSuggestions.Considered.Accepted"/>
+  <affected-action name="TabsSuggestions.Considered.Dismissed"/>
+  <affected-action name="TabsSuggestions.NotConsidered"/>
+</action-suffix>
+
 </actions>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 55fe4c2..a6d5cbbc 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -21256,6 +21256,7 @@
   <int value="738" label="ExtensionInstallAllowlist"/>
   <int value="739" label="ShowFullUrlsInAddressBar"/>
   <int value="740" label="ExtensionInstallBlocklist"/>
+  <int value="741" label="ReportDeviceSystemInfo"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
@@ -28505,6 +28506,8 @@
   <int value="3347" label="RTCAdaptivePtime"/>
   <int value="3348"
       label="HTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest"/>
+  <int value="3349" label="NavigationTimingL2"/>
+  <int value="3350" label="ResourceTiming"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -53244,12 +53247,13 @@
   <int value="6" label="Opened automatically / Auto-signin toast"/>
   <int value="7" label="Opened manually / Offering a password to update"/>
   <int value="8" label="Opened automatically / Offering a password to update"/>
-  <int value="9"
+  <int value="9" label="Opened manually / Confirming generated password saved"/>
+  <int value="10"
       label="Opened automatically / Offering to save unsynced passwords
              locally"/>
-  <int value="10"
-      label="Opened automatically / Notification about compromised passwords"/>
   <int value="11"
+      label="Opened automatically / Notification about compromised passwords"/>
+  <int value="12"
       label="Opened automatically / Offering to move profile password to
              account store"/>
 </enum>
@@ -54399,9 +54403,9 @@
   <int value="2" label="Clicked 'Nope'"/>
   <int value="3" label="Clicked 'Never'"/>
   <int value="4" label="Clicked 'Manage passwords'"/>
-  <int value="5" label="Clicked 'Done'"/>
+  <int value="5" label="Clicked 'Done' (obsolete)"/>
   <int value="6" label="Clicked 'Unblacklist' (obsolete)"/>
-  <int value="7" label="Clicked 'OK'"/>
+  <int value="7" label="Clicked 'OK' (obsolete)"/>
   <int value="8" label="Clicked on a credential (obsolete)"/>
   <int value="9" label="Auto-signin toast timeout"/>
   <int value="10" label="Auto-signin toast clicked (obsolete)"/>
@@ -62550,6 +62554,7 @@
   <int value="5" label="Sent for blocked embedder"/>
   <int value="6" label="Throttled for too many undrawn frames"/>
   <int value="7" label="Sent by default"/>
+  <int value="8" label="Throttled by client request"/>
 </enum>
 
 <enum name="SendPasswordFormToBrowserProcess">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 74937cc..7b2860a 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4628,7 +4628,7 @@
 </histogram>
 
 <histogram name="Android.SelectFileDialogImgCount" units="images"
-    expires_after="2020-08-25">
+    expires_after="2021-07-17">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -4640,7 +4640,7 @@
 </histogram>
 
 <histogram name="Android.SelectFileDialogScope" enum="SelectFileDialogScope"
-    expires_after="2020-08-25">
+    expires_after="2021-07-17">
   <owner>peter@chromium.org</owner>
   <owner>finnur@chromium.org</owner>
   <summary>
@@ -57427,6 +57427,17 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Extensions.ForceInstalledTime" units="ms"
+    expires_after="2020-11-01">
+  <owner>swapnilgupta@google.com</owner>
+  <owner>burunduk@chromium.org</owner>
+  <owner>managed-devices@google.com</owner>
+  <summary>
+    The amount of time elapsed during different stage of the installation
+    process for the enterprise policy forced extensions.
+  </summary>
+</histogram>
+
 <histogram name="Extensions.ForceInstalledTimedOutAndNotInstalledCount"
     units="units" expires_after="2020-11-01">
   <owner>burunduk@chromium.org</owner>
@@ -118735,6 +118746,42 @@
   </summary>
 </histogram>
 
+<histogram name="PageLoad.Clients.Ads.AdDensity.MaxPercentByArea" units="%"
+    expires_after="2020-10-08">
+  <owner>justinmron@chromium.org</owner>
+  <owner>johnidel@chromium.org</owner>
+  <summary>
+    The page's maximum ad density by area over its lifecycle as a percent from
+    0-100. The density measurement is throttled in page load metrics propagation
+    from renderer to browser and in the ads page load metrics observer, this may
+    lead to inaccurate maximum density. Recorded at the time a page is
+    destroyed.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight" units="%"
+    expires_after="2020-10-08">
+  <owner>justinmron@chromium.org</owner>
+  <owner>johnidel@chromium.org</owner>
+  <summary>
+    The page's maximum ad density by height over its lifecycle as a percent from
+    0-100. The density measurement is throttled in page load metrics propagation
+    from renderer to browser and in the ads page load metrics observer, this may
+    lead to inaccurate maximum density. Recorded at the time a page is
+    destroyed.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Clients.Ads.AdDensity.Recorded" units="Boolean"
+    expires_after="2020-10-08">
+  <owner>justinmron@chromium.org</owner>
+  <owner>johnidel@chromium.org</owner>
+  <summary>
+    Whether the ad density was recorded on the page for both density by area and
+    density by height. Recorded at the time a page is destroyed.
+  </summary>
+</histogram>
+
 <histogram name="PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd"
     enum="DidNavigateToAd" expires_after="2018-07-13">
   <obsolete>
@@ -177639,6 +177686,10 @@
 
 <histogram name="Tabs.Suggestions.Close.NumSuggestionsChanged" units="count"
     expires_after="2020-11-01">
+  <obsolete>
+    Removed as of 07/2020. Rename to
+    Tabs.Suggestions.NumSuggestionsChanged.Closing.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>davidjm@chromium.org</owner>
   <summary>
@@ -177653,6 +177704,27 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Tabs.Suggestions.NumSuggestionsChanged"
+    units="count" expires_after="2020-11-01">
+  <owner>yusufo@chromium.org</owner>
+  <owner>davidjm@chromium.org</owner>
+  <owner>meiliang@chromium.org</owner>
+  <summary>
+    The user is presented with recommendations on which Tabs they could take the
+    suggested action. The user has the option to: 1) Remove a Tab from the
+    recommendation 2) Add a Tab which wasn't in the recommendation to the
+    recommendation.
+
+    This metric records the sum of the number of times the user does 1) or 2)
+    and is a measure of how useful the recommendation is. This metric is
+    recorded after the user accepts a recommendation - potentially with edits by
+    performing 1) or 2).
+
+    Note: Adding and removing the same Tab, or vice versa, would be counted as
+    0.
+  </summary>
+</histogram>
+
 <histogram name="Tabs.SwitchFromCloseLatency" units="ms" expires_after="M88">
   <owner>dtrainor@chromium.org</owner>
   <owner>yusufo@chromium.org</owner>
@@ -179349,21 +179421,23 @@
 <histogram name="TopSites.NumberOfApplyBlacklist" units="units"
     expires_after="2018-08-30">
   <obsolete>
-    Long removed.
+    Removed in M86.
   </obsolete>
   <owner>alemate@chromium.org</owner>
-  <summary>The number of times TopSitesImpl::ApplyBlacklist is called.</summary>
+  <summary>
+    The number of times TopSitesImpl::ApplyBlockedUrls is called.
+  </summary>
 </histogram>
 
 <histogram name="TopSites.NumberOfBlacklistedItems" units="units"
     expires_after="2018-08-30">
   <obsolete>
-    Long removed.
+    Removed in M86.
   </obsolete>
   <owner>alemate@chromium.org</owner>
   <summary>
-    The number of items in the user Most Visited blacklist every time
-    TopSitesImpl::ApplyBlacklist is called.
+    The number of urls blocked in TopSites. Logged every time
+    TopSitesImpl::ApplyBlockedUrls is called.
   </summary>
 </histogram>
 
@@ -202141,6 +202215,12 @@
   <affected-histogram name="Extensions.Functions.SucceededTime"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="ExtensionInstallStages" separator=".">
+  <suffix name="DownloadingStartTo.ManifestDownloadComplete"
+      label="Time taken to complete download of update manifest"/>
+  <affected-histogram name="Extensions.ForceInstalledTime"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="ExtensionMessagingPortCreationTime" separator=".">
   <suffix name="InBeforeUnload"
       label="Created during an event handler for the 'beforeunload' event.">
@@ -214348,6 +214428,16 @@
   <affected-histogram name="Tabs.UsedInInterval.Count"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="TabSuggestionType" separator=".">
+  <suffix name="ClosingSuggestion"
+      label="This bukect is for the closing suggestion. It suggests users to
+             close the recommended tabs."/>
+  <suffix name="GroupingSuggestion"
+      label="This bukect is for the grouping suggestion. It suggests users to
+             group the recommended tabs."/>
+  <affected-histogram name="Tabs.Suggestions.NumSuggestionsChanged"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="TabSwitchingType" separator=".">
   <suffix name="NoSavedFrames"
       label="The time from the input timestamp on a tab switch, until the
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 3b3d27c..f2cf5085 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -345,6 +345,22 @@
       bucket (with a bucket ratio of 1.3).
     </summary>
   </metric>
+  <metric name="MaxAdDensityByArea">
+    <summary>
+      The estimated maximum density of ads on a page by area. Calculated as the
+      area of ads on the page * 100 / page area. This counts each overlapping
+      area once, it may be inaccurate due to updates and calculations being
+      throttled.
+    </summary>
+  </metric>
+  <metric name="MaxAdDensityByHeight">
+    <summary>
+      The estimated maximum density of ads on a page by height. Calculated as
+      the combined height of ads on the page * 100 / page height. This counts
+      each overlapping area once, it may be inaccurate due to updates and
+      calculations being throttled.
+    </summary>
+  </metric>
   <metric name="TotalBytes">
     <summary>
       Amount of network bytes used to load resources on the page. Includes
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 1259786..7b6cf35 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "eabadb18c9b973545e0c496332e868019f16ca0c",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/d9b254b474d3ad65d26ece05b51eb6c7a0ff5f35/trace_processor_shell.exe"
+            "hash": "2ccd0e79a314e7ee6f6541d707cf5a0018768287",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/c0f23a129f67b27198beac0193cb16814d36485a/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "ee514396d2e9a5059923db3926ac0a74ab0b9e12",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/df50009d3edec39cee9a7f5a59851701848fa32d/trace_processor_shell"
+            "hash": "a66f305fecc7fac84c46bc5556c317c9fd0fb4bd",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c0f23a129f67b27198beac0193cb16814d36485a/trace_processor_shell"
         },
         "linux": {
-            "hash": "e8747f4901f0211546d40c9aac0bfb3e69b97a8b",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/d9b254b474d3ad65d26ece05b51eb6c7a0ff5f35/trace_processor_shell"
+            "hash": "580d7c6bd17f3c70bb84c283ec28191196e03451",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/c0f23a129f67b27198beac0193cb16814d36485a/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 8f196f5..2d3528e 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -169,6 +169,9 @@
  <item id="mojo_context_state" hash_code="93232258" type="0" deprecated="2017-10-20" content_hash_code="124821232" file_path=""/>
  <item id="navigation_predictor_srp_prefetch" hash_code="57773453" type="0" content_hash_code="38811322" os_list="linux,windows" file_path="chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc"/>
  <item id="navigation_url_loader" hash_code="63171670" type="0" content_hash_code="129352907" os_list="linux,windows" file_path="content/browser/loader/navigation_url_loader_impl.cc"/>
+ <item id="nearby_share_contacts" hash_code="91999155" type="1" second_id="29188932" content_hash_code="74684570" os_list="linux,windows" semantics_fields="1,2,3,4,5" policy_fields="3,4" file_path="chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc"/>
+ <item id="nearby_share_list_public_certificates" hash_code="123714070" type="1" second_id="29188932" content_hash_code="24145546" os_list="linux,windows" semantics_fields="1,2,3,4,5" policy_fields="3,4" file_path="chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc"/>
+ <item id="nearby_share_update_device" hash_code="30656793" type="1" second_id="29188932" content_hash_code="30624346" os_list="linux,windows" semantics_fields="1,2,3,4,5" policy_fields="3,4" file_path="chrome/browser/nearby_sharing/client/nearby_share_client_impl.cc"/>
  <item id="nearby_webrtc_connection" hash_code="37994740" type="0" content_hash_code="118366066" os_list="linux,windows" file_path="chrome/services/sharing/nearby/platform_v2/webrtc.cc"/>
  <item id="net_error_helper" hash_code="60071001" type="0" deprecated="2020-07-10" content_hash_code="68322861" file_path=""/>
  <item id="network_location_provider" hash_code="23472048" type="1" second_id="96590038" content_hash_code="41087976" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="services/device/geolocation/network_location_provider.cc"/>
diff --git a/ui/gl/gl_utils.cc b/ui/gl/gl_utils.cc
index 6e87f0d..ea3a57d 100644
--- a/ui/gl/gl_utils.cc
+++ b/ui/gl/gl_utils.cc
@@ -12,6 +12,10 @@
 #include "ui/gl/gl_features.h"
 #include "ui/gl/gl_switches.h"
 
+#if defined(USE_EGL)
+#include "ui/gl/gl_surface_egl.h"
+#endif  // defined(USE_EGL)
+
 #if defined(OS_ANDROID)
 #include "base/posix/eintr_wrapper.h"
 #include "third_party/libsync/src/include/sync/sync.h"
@@ -81,6 +85,21 @@
   }
 }
 
+bool PassthroughCommandDecoderSupported() {
+#if defined(USE_EGL)
+  // Using the passthrough command buffer requires that specific ANGLE
+  // extensions are exposed
+  return gl::GLSurfaceEGL::IsCreateContextBindGeneratesResourceSupported() &&
+         gl::GLSurfaceEGL::IsCreateContextWebGLCompatabilitySupported() &&
+         gl::GLSurfaceEGL::IsRobustResourceInitSupported() &&
+         gl::GLSurfaceEGL::IsDisplayTextureShareGroupSupported() &&
+         gl::GLSurfaceEGL::IsCreateContextClientArraysSupported();
+#else
+  // The passthrough command buffer is only supported on top of ANGLE/EGL
+  return false;
+#endif  // defined(USE_EGL)
+}
+
 #if defined(OS_WIN)
 // This function is thread safe.
 bool AreOverlaysSupportedWin() {
diff --git a/ui/gl/gl_utils.h b/ui/gl/gl_utils.h
index 32eacda..ea56eb8 100644
--- a/ui/gl/gl_utils.h
+++ b/ui/gl/gl_utils.h
@@ -26,6 +26,8 @@
 GL_EXPORT bool UsePassthroughCommandDecoder(
     const base::CommandLine* command_line);
 
+GL_EXPORT bool PassthroughCommandDecoderSupported();
+
 #if defined(OS_WIN)
 GL_EXPORT bool AreOverlaysSupportedWin();
 #endif
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index 685cd8fc..fa04ef64 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -175,10 +175,23 @@
   DCHECK(drm_thread_.task_runner()) << "DrmThreadProxy::AddDrmDeviceReceiver "
                                        "drm_thread_ task runner missing";
 
-  drm_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&DrmThread::AddDrmDeviceReceiver,
-                     base::Unretained(&drm_thread_), std::move(receiver)));
+  if (drm_thread_.task_runner()->BelongsToCurrentThread()) {
+    drm_thread_.AddDrmDeviceReceiver(std::move(receiver));
+  } else {
+    drm_thread_.task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&DrmThread::AddDrmDeviceReceiver,
+                       base::Unretained(&drm_thread_), std::move(receiver)));
+  }
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+DrmThreadProxy::GetDrmThreadTaskRunner() {
+  return drm_thread_.task_runner();
+}
+
+bool DrmThreadProxy::WaitUntilDrmThreadStarted() {
+  return drm_thread_.WaitUntilThreadStarted();
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
index 303a7eb..5b55beee 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -83,6 +83,9 @@
   void AddDrmDeviceReceiver(
       mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver);
 
+  bool WaitUntilDrmThreadStarted();
+  scoped_refptr<base::SingleThreadTaskRunner> GetDrmThreadTaskRunner();
+
  private:
   DrmThread drm_thread_;
 
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index 9e0cc716..4e81e147 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -101,26 +101,50 @@
   // In multi-process mode, this function must be executed in Viz as it sets up
   // the callbacks needed for Mojo receivers. In single process mode, it may be
   // called on any thread. It must follow one of |InitializeUI| or
-  // |InitializeGPU|. While the caller may choose to invoke this method before
-  // entering the sandbox, the actual interface adding has to happen on the DRM
-  // Device thread and so will be deferred until the DRM thread is running.
+  // |InitializeGPU|.
   void AddInterfaces(mojo::BinderMap* binders) override {
-    binders->Add<ozone::mojom::DrmDevice>(
-        base::BindRepeating(&OzonePlatformGbm::CreateDrmDeviceReceiver,
-                            weak_factory_.GetWeakPtr()),
-        base::ThreadTaskRunnerHandle::Get());
+    if (single_process()) {
+      // This logic in multi-process mode causes deadlock to happen, where
+      // |gpu_task_runner_| blocks on drm_thread while drm_thread has not
+      // received DrmDevice mojo endpoint. Hence, the caller should invoke this
+      // method after drm_thread is started.
+      binders->Add<ozone::mojom::DrmDevice>(
+          base::BindRepeating(
+              &OzonePlatformGbm::CreateDrmDeviceReceiverOnGpuThread,
+              weak_factory_.GetWeakPtr()),
+          gpu_task_runner_);
+    } else {
+      // In multi-process mode DRM thread is started right after sandbox entry,
+      // |AddInterfaces| is invoked from VizMainImpl so DRM thread must have
+      // been started. |WaitUntilDrmThreadStarted| is not expected to do a real
+      // wait but helps assuming that the task runner exists.
+      drm_thread_proxy_->WaitUntilDrmThreadStarted();
+      // There's no need for binder callback to bounce on |gpu_task_runner_|.
+      // Binder callbacks should directly run on DRM thread.
+      binders->Add<ozone::mojom::DrmDevice>(
+          base::BindRepeating(
+              &OzonePlatformGbm::CreateDrmDeviceReceiverOnDrmThread,
+              weak_factory_.GetWeakPtr()),
+          drm_thread_proxy_->GetDrmThreadTaskRunner());
+    }
   }
 
-  // Runs on the thread where AddInterfaces was invoked. But the endpoint is
-  // always bound on the DRM thread.
-  void CreateDrmDeviceReceiver(
+  // Runs on the gpu thread. But the endpoint is always bound on the DRM thread.
+  void CreateDrmDeviceReceiverOnGpuThread(
       mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver) {
+    CHECK(single_process());
     if (drm_thread_started_)
       drm_thread_proxy_->AddDrmDeviceReceiver(std::move(receiver));
     else
       pending_gpu_adapter_receivers_.push_back(std::move(receiver));
   }
 
+  void CreateDrmDeviceReceiverOnDrmThread(
+      mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver) {
+    CHECK(!single_process());
+    drm_thread_proxy_->AddDrmDeviceReceiver(std::move(receiver));
+  }
+
   // Runs on the thread that invoked |AddInterfaces| to drain the queue of
   // receiver requests that could not be satisfied until the DRM thread is
   // available (i.e. if waiting until the sandbox has been entered.)
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index 1760374..6107611 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -226,7 +226,10 @@
   bool initialized_gpu_ = false;
   bool prearly_initialized_ = false;
 
-  bool single_process_ = false;
+  // This value is checked on multiple threads. Declaring it volatile makes
+  // modifications to |single_process_| visible by other threads. Mutex is not
+  // needed since it's set before other threads are started.
+  volatile bool single_process_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(OzonePlatform);
 };
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 25efa36..a30defd9 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -576,7 +576,9 @@
     gfx::ImageSkia icon_skia =
         GetImageSkiaFromImageModel(&icon, GetNativeTheme());
     int icon_y = y + (contents_height - icon_skia.height()) / 2;
-    canvas->DrawImageInt(icon_skia, x, icon_y);
+    gfx::Rect icon_bounds(x, icon_y, icon_skia.width(), icon_skia.height());
+    AdjustBoundsForRTLUI(&icon_bounds);
+    canvas->DrawImageInt(icon_skia, icon_bounds.x(), icon_bounds.y());
     x += icon_skia.width() + LayoutProvider::Get()->GetDistanceMetric(
                                  DISTANCE_RELATED_LABEL_HORIZONTAL);
   }
diff --git a/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn
index 6c1f0d8..a3690d9 100644
--- a/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn
@@ -11,12 +11,18 @@
 # JS type check for Polymer 2 and 3
 
 js_type_check("closure_compile") {
-  deps = [ ":network_health_summary" ]
+  deps = [
+    ":network_diagnostics",
+    ":network_health_summary",
+  ]
 }
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [ ":network_health_summary.m" ]
+  deps = [
+    ":network_diagnostics.m",
+    ":network_health_summary.m",
+  ]
 }
 
 # Sources with Polymer 3 generated modules
@@ -29,6 +35,13 @@
   ]
 }
 
+js_library("network_diagnostics") {
+  deps = [
+    "//chromeos/services/network_health/public/mojom:mojom_js_library_for_compile",
+    "//ui/webui/resources/js:i18n_behavior",
+  ]
+}
+
 js_library("network_health_summary.m") {
   sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network_health/network_health_summary.m.js" ]
   deps = [
@@ -40,6 +53,15 @@
   extra_deps = [ ":network_health_summary_module" ]
 }
 
+js_library("network_diagnostics.m") {
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.m.js" ]
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:i18n_behavior.m",
+  ]
+  extra_deps = [ ":network_diagnostics_module" ]
+}
+
 # polymer_modulizer for converting Polymer2 to Polymer3
 
 polymer_modulizer("network_health_summary") {
@@ -48,6 +70,15 @@
   html_type = "dom-module"
 }
 
+polymer_modulizer("network_diagnostics") {
+  js_file = "network_diagnostics.js"
+  html_file = "network_diagnostics.html"
+  html_type = "dom-module"
+}
+
 group("polymer3_elements") {
-  public_deps = [ ":network_health_summary_module" ]
+  public_deps = [
+    ":network_diagnostics_module",
+    ":network_health_summary_module",
+  ]
 }
diff --git a/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.html b/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.html
new file mode 100644
index 0000000..0afb97e
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.html
@@ -0,0 +1,79 @@
+<link rel="import" href="../../../html/polymer.html">
+
+<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html">
+<link rel="import" href="chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
+<link rel="import" href="../../../cr_elements/cr_button/cr_button.html">
+<link rel="import" href="../../../html/i18n_behavior.html">
+
+<dom-module id="network-diagnostics">
+  <template>
+    <style>
+      .routine-group {
+        display: inline-flex;
+        flex-wrap: wrap;
+      }
+
+      .routine-container {
+        border: 2px solid rgb(150, 150, 150);
+        height: 50px;
+        margin: 10px;
+        padding: 5px;
+        width: 400px;
+      }
+
+      .run-btn {
+        background-color: white;
+      }
+
+      .routine-name {
+        font-size: 1rem;
+        font-weight: bold;
+      }
+
+      .routine-content {
+        display: flex;
+      }
+
+      .routine-result {
+        flex: 1;
+      }
+
+      .result-passed {
+        background-color: rgb(217, 234, 211);
+      }
+
+      .result-error {
+        background-color: rgb(244, 204, 204);
+      }
+
+      .result-not-run {
+        background-color: rgb(255, 242, 204);
+      }
+    </style>
+    <div>
+      <cr-button class="action-button" on-click="onRunAllRoutinesClick_">
+        [[i18n('NetworkDiagnosticsRunAll')]]
+      </cr-button>
+    </div>
+    <div class="routine-group">
+      <template is="dom-repeat" items="[[routines_]]" as="routine">
+        <div class="routine-container">
+          <div class="routine-name">[[i18n(routine.name)]]</div>
+          <div class="routine-content">
+            <span class="routine-result">[[routine.resultMsg]]</span>
+
+            <template is="dom-if" if="[[routine.running]]">
+              <paper-spinner-lite active></paper-spinner-lite>
+            </template>
+
+            <cr-button class="run-btn" hidden="[[routine.running]]" on-click="onRunRoutineClick_">
+              [[i18n('NetworkDiagnosticsRun')]]
+            </cr-button>
+          </div>
+        </div>
+      </template>
+    </div>
+  </template>
+  <script src="network_diagnostics.js"></script>
+</dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.js b/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.js
new file mode 100644
index 0000000..a27abe9
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.js
@@ -0,0 +1,191 @@
+
+// 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.
+
+/**
+ * @fileoverview Polymer element for interacting with Network Diagnostics.
+ */
+
+/**
+ * A network diagnostics routine. Holds descriptive information about the
+ * routine, and it's transient state.
+ * @typedef {{
+ *   name: string,
+ *   type: !RoutineType,
+ *   running: boolean,
+ *   resultMsg: string,
+ * }}
+ */
+let Routine;
+
+/**
+ * A routine response from the Network Diagnostics mojo service.
+ * @typedef {{
+ *   verdict: chromeos.networkDiagnostics.mojom.RoutineVerdict
+ * }}
+ */
+let RoutineResponse;
+
+/**
+ * Definition for all Network diagnostic routine types. This enum is intended
+ * to be used as an index in an array of routines.
+ * @enum {number}
+ */
+const RoutineType = {
+  LAN_CONNECTIVITY: 0,
+  SIGNAL_STRENGTH: 1,
+  GATEWAY_PING: 2,
+  SECURE_WIFI: 3,
+  DNS_RESOLVER: 4,
+  DNS_LATENCY: 5,
+  DNS_RESOLUTION: 6,
+};
+
+/**
+ * Helper function to create a routine object.
+ * @param {string} name
+ * @param {!RoutineType} type
+ * @return {!Routine} Routine object
+ */
+function createRoutine(name, type) {
+  return {name: name, type: type, running: false, resultMsg: ''};
+}
+
+Polymer({
+  is: 'network-diagnostics',
+
+  behaviors: [
+    I18nBehavior,
+  ],
+
+  properties: {
+    /**
+     * List of Diagnostics Routines
+     * @private {!Array<!Routine>}
+     */
+    routines_: {
+      type: Array,
+      value: function() {
+        const routines = [];
+        routines[RoutineType.LAN_CONNECTIVITY] = createRoutine(
+            'NetworkDiagnosticsLanConnectivity', RoutineType.LAN_CONNECTIVITY);
+        routines[RoutineType.SIGNAL_STRENGTH] = createRoutine(
+            'NetworkDiagnosticsSignalStrength', RoutineType.SIGNAL_STRENGTH);
+        routines[RoutineType.GATEWAY_PING] = createRoutine(
+            'NetworkDiagnosticsGatewayCanBePinged', RoutineType.GATEWAY_PING);
+        routines[RoutineType.SECURE_WIFI] = createRoutine(
+            'NetworkDiagnosticsHasSecureWiFiConnection',
+            RoutineType.SECURE_WIFI);
+        routines[RoutineType.DNS_RESOLVER] = createRoutine(
+            'NetworkDiagnosticsDnsResolverPresent', RoutineType.DNS_RESOLVER);
+        routines[RoutineType.DNS_LATENCY] = createRoutine(
+            'NetworkDiagnosticsDnsLatency', RoutineType.DNS_LATENCY);
+        routines[RoutineType.DNS_RESOLUTION] = createRoutine(
+            'NetworkDiagnosticsDnsResolution', RoutineType.DNS_RESOLUTION);
+        return routines;
+      }
+    }
+  },
+
+  /**
+   * Network Diagnostics mojo remote.
+   * @private {
+   *     ?chromeos.networkDiagnostics.mojom.NetworkDiagnosticsRoutinesRemote}
+   */
+  networkDiagnostics_: null,
+
+  /** @override */
+  created() {
+    this.networkDiagnostics_ = chromeos.networkDiagnostics.mojom
+                                   .NetworkDiagnosticsRoutines.getRemote();
+  },
+
+  /** @private */
+  onRunAllRoutinesClick_() {
+    for (const routine of this.routines_) {
+      this.runRoutine_(routine.type);
+    }
+  },
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onRunRoutineClick_(event) {
+    this.runRoutine_(event.model.index);
+  },
+
+  /**
+   * @param {!RoutineType} type
+   * @private
+   */
+  runRoutine_(type) {
+    this.set(`routines_.${type}.running`, true);
+    this.set(`routines_.${type}.resultMsg`, '');
+    const element =
+        this.shadowRoot.querySelectorAll('.routine-container')[type];
+    element.classList.remove('result-passed', 'result-error', 'result-not-run');
+    switch (type) {
+      case RoutineType.LAN_CONNECTIVITY:
+        this.networkDiagnostics_.lanConnectivity().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+      case RoutineType.SIGNAL_STRENGTH:
+        this.networkDiagnostics_.signalStrength().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+      case RoutineType.GATEWAY_PING:
+        this.networkDiagnostics_.gatewayCanBePinged().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+      case RoutineType.SECURE_WIFI:
+        this.networkDiagnostics_.hasSecureWiFiConnection().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+      case RoutineType.DNS_RESOLVER:
+        this.networkDiagnostics_.dnsResolverPresent().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+      case RoutineType.DNS_LATENCY:
+        this.networkDiagnostics_.dnsLatency().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+      case RoutineType.DNS_RESOLUTION:
+        this.networkDiagnostics_.dnsResolution().then(
+            result => this.evaluateRoutine_(type, result));
+        break;
+    }
+  },
+
+  /**
+   * @param {!RoutineType} type
+   * @param {!RoutineResponse} result
+   * @private
+   */
+  evaluateRoutine_(type, result) {
+    const routine = `routines_.${type}`;
+    this.set(`${routine}.running`, false);
+
+    const element =
+        this.shadowRoot.querySelectorAll('.routine-container')[type];
+    let resultMsg = '';
+
+    switch (result.verdict) {
+      case chromeos.networkDiagnostics.mojom.RoutineVerdict.kNoProblem:
+        resultMsg = this.i18n('NetworkDiagnosticsPassed');
+        element.classList.add('result-passed');
+        break;
+      case chromeos.networkDiagnostics.mojom.RoutineVerdict.kProblem:
+        resultMsg = this.i18n('NetworkDiagnosticsFailed');
+        element.classList.add('result-error');
+        break;
+      case chromeos.networkDiagnostics.mojom.RoutineVerdict.kNotRun:
+        resultMsg = this.i18n('NetworkDiagnosticsNotRun');
+        element.classList.add('result-not-run');
+        break;
+    }
+
+    this.set(routine + '.resultMsg', resultMsg);
+  },
+});
diff --git a/ui/webui/resources/cr_components/cr_components_resources.grdp b/ui/webui/resources/cr_components/cr_components_resources.grdp
index a955317a..4afaa4e 100644
--- a/ui/webui/resources/cr_components/cr_components_resources.grdp
+++ b/ui/webui/resources/cr_components/cr_components_resources.grdp
@@ -264,6 +264,12 @@
     <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_HEALTH_SUMMARY_JS"
                file="cr_components/chromeos/network_health/network_health_summary.js"
                type="chrome_html" />
+    <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_DIAGNOSTICS_HTML"
+               file="cr_components/chromeos/network_health/network_diagnostics.html"
+               type="chrome_html" />
+    <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_DIAGNOSTICS_JS"
+               file="cr_components/chromeos/network_health/network_diagnostics.js"
+               type="chrome_html" />
 
     <!-- Shared between settings and add new share flow. -->
     <structure name="IDR_WEBUI_CHROMEOS_SMB_SHARES_SMB_BROWSER_PROXY_HTML"
diff --git a/weblayer/browser/translate_compact_infobar.cc b/weblayer/browser/translate_compact_infobar.cc
index 63b18f4..808fb81 100644
--- a/weblayer/browser/translate_compact_infobar.cc
+++ b/weblayer/browser/translate_compact_infobar.cc
@@ -205,6 +205,11 @@
 void TranslateCompactInfoBar::OnTranslateStepChanged(
     translate::TranslateStep step,
     translate::TranslateErrors::Type error_type) {
+  // If the tab lost active state while translation was occurring, the Java
+  // infobar will now be gone. In that case there is nothing to do here.
+  if (!HasSetJavaInfoBar())
+    return;  // No connected Java infobar
+
   if (!owner())
     return;  // We're closing; don't call anything.