diff --git a/DEPS b/DEPS
index c9e1757..69cfddf1 100644
--- a/DEPS
+++ b/DEPS
@@ -133,11 +133,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': '673c538f8d74ff5a2ac8f81ed3f6364253c04f7a',
+  'skia_revision': '93b94512391327fb74b07d162aac8f1f677375f4',
   # 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': 'f7cc35d707c060d94ce8d3ef4855055752ceea42',
+  'v8_revision': 'e51a5299c81b118cfb084568b1f5241af4d96c54',
   # 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.
@@ -145,11 +145,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '4e87659e289c37602e3c94264e7302fe7a8dfaa7',
+  'angle_revision': '494afea985e678cbefb3de80a816f3f54762bea6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '25ec7b0cd393f08c41f35fbf86c65d7828759b8c',
+  'swiftshader_revision': '6480d4e10cb57f36baa2b03f8eb40b8d04f0e39f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -196,7 +196,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '293a9a2e27bad0075e68b614c14efa79d0818c1a',
+  'catapult_revision': '2afe880da0ce34181cbfbc2d95550aa6e589537a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -248,7 +248,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '9d29c37ac507a67272da548d85e90fac4befecc1',
+  'spv_tools_revision': '6df8a917a4496f1a46e8ae21ffa3d00075380e47',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -760,7 +760,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '6b83d6b9933549a371076c6b5a439453a847d168',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ede69d84cfc7290b7f44a4bccb566c70f6839808',
       'condition': 'checkout_linux',
   },
 
@@ -785,7 +785,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8b94108e684872a89f7108f51ba74f01220d64fa',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'deb384f985d00de73ee29a65760b826f08a60983',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1298,7 +1298,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '208634763a17606672e6bc3ecad01387bff9deea',
+    Var('webrtc_git') + '/src.git' + '@' + 'cc3503248f1dc7edd3ab505b5194c69718d0f711',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1339,7 +1339,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@62079cb0286869f82f886f9fa45873ce26796633',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a94bdfdb451cfc9d285f7c89c1e96c4fdb554338',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 8943046..119dfe65 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -208,9 +208,6 @@
 
 
 _BANNED_CPP_FUNCTIONS = (
-    # Make sure that gtest's FRIEND_TEST() macro is not used; the
-    # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
-    # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
     (
       r'\bNULL\b',
       (
@@ -219,6 +216,9 @@
       True,
       (),
     ),
+    # Make sure that gtest's FRIEND_TEST() macro is not used; the
+    # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
+    # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
     (
       'FRIEND_TEST(',
       (
@@ -591,6 +591,17 @@
       True,
       (),
     ),
+    (
+      'DEFINE_TYPE_CASTS',
+      (
+        'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
+        '//third_party/blink/renderer/platform/casting.h.'
+      ),
+      True,
+      (
+        r'^third_party/blink/renderer/.*\.(cc|h)$',
+      ),
+    ),
 )
 
 
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index ccad462..e7c16ac 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -946,7 +946,7 @@
     "//device/gamepad:java",
     "//net/android:net_java",
     "//services/network/public/mojom:mojom_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/blink/public:blink_headers_java",
     "//ui/android:ui_java",
   ]
@@ -1047,7 +1047,7 @@
 
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
 
   # The appropriate .class file will be loaded via a dependency to a library
diff --git a/android_webview/browser/gfx/surfaces_instance.cc b/android_webview/browser/gfx/surfaces_instance.cc
index f04202a..ec79f72a 100644
--- a/android_webview/browser/gfx/surfaces_instance.cc
+++ b/android_webview/browser/gfx/surfaces_instance.cc
@@ -264,8 +264,9 @@
   render_pass->SetNew(1, rect, rect, gfx::Transform());
   viz::SharedQuadState* quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                     are_contents_opaque, 1.f, SkBlendMode::kSrcOver, 0);
+  quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                     is_clipped, are_contents_opaque, 1.f,
+                     SkBlendMode::kSrcOver, 0);
   viz::SolidColorDrawQuad* solid_quad =
       render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
   solid_quad->SetNew(quad_state, rect, rect, SK_ColorBLACK, false);
diff --git a/android_webview/tools/automated_ui_tests/BUILD.gn b/android_webview/tools/automated_ui_tests/BUILD.gn
index f40cc0de..8a84ad7 100644
--- a/android_webview/tools/automated_ui_tests/BUILD.gn
+++ b/android_webview/tools/automated_ui_tests/BUILD.gn
@@ -57,7 +57,7 @@
     ":webview_ui_test_app_java",
     "//base:base_java",
     "//base:base_java_test_support",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/android_tools:android_test_base_java",
diff --git a/android_webview/tools/cts_config/webview_cts_gcs_path.json b/android_webview/tools/cts_config/webview_cts_gcs_path.json
index 5cc30cf..3c183ba 100644
--- a/android_webview/tools/cts_config/webview_cts_gcs_path.json
+++ b/android_webview/tools/cts_config/webview_cts_gcs_path.json
@@ -213,10 +213,6 @@
           {
             "match": "android.webkit.cts.WebViewSslTest#testSecureServerRequiringClientCertDoesCancelRequest",
             "_bug_id": "crbug.com/922400"
-          },
-          {
-            "match": "android.webkit.cts.WebViewTest#testLoadDataWithBaseUrl",
-            "_bug_id": "crbug.com/900915"
           }
         ]
       },
@@ -248,10 +244,6 @@
           {
             "match": "android.webkit.cts.WebViewSslTest#testSecureServerRequiringClientCertDoesCancelRequest",
             "_bug_id": "crbug.com/922400"
-          },
-          {
-            "match": "android.webkit.cts.WebViewTest#testLoadDataWithBaseUrl",
-            "_bug_id": "crbug.com/900915"
           }
         ]
       },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index fd65797..09e42768 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -454,6 +454,8 @@
     "metrics/demo_session_metrics_recorder.h",
     "metrics/desktop_task_switch_metric_recorder.cc",
     "metrics/desktop_task_switch_metric_recorder.h",
+    "metrics/histogram_macros.cc",
+    "metrics/histogram_macros.h",
     "metrics/login_metrics_recorder.cc",
     "metrics/login_metrics_recorder.h",
     "metrics/pip_uma.h",
@@ -1666,6 +1668,7 @@
     "media/media_notification_view_unittest.cc",
     "metrics/demo_session_metrics_recorder_unittest.cc",
     "metrics/desktop_task_switch_metric_recorder_unittest.cc",
+    "metrics/histogram_macros_unittest.cc",
     "metrics/login_metrics_recorder_unittest.cc",
     "metrics/pointer_metrics_recorder_unittest.cc",
     "metrics/task_switch_metrics_recorder_unittest.cc",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 68953804..3cc430544 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "ash/app_list/app_list_controller_observer.h"
+#include "ash/app_list/app_list_metrics.h"
 #include "ash/app_list/app_list_presenter_delegate_impl.h"
 #include "ash/app_list/model/app_list_folder_item.h"
 #include "ash/app_list/model/app_list_item.h"
@@ -916,6 +917,10 @@
     client_->LogSearchClick(result_id, suggestion_index, launched_from);
 }
 
+void AppListControllerImpl::LogSearchAbandonHistogram() {
+  app_list::RecordSearchAbandonWithQueryLengthHistogram(GetLastQueryLength());
+}
+
 void AppListControllerImpl::InvokeSearchResultAction(
     const std::string& result_id,
     int action_index,
@@ -952,6 +957,9 @@
 }
 
 void AppListControllerImpl::ViewClosing() {
+  if (presenter_.GetView()->search_box_view()->is_search_box_active())
+    LogSearchAbandonHistogram();
+
   CloseAssistantUi(AssistantExitPoint::kLauncherClose);
   if (client_)
     client_->ViewClosing();
@@ -1235,4 +1243,8 @@
   }
 }
 
+int AppListControllerImpl::GetLastQueryLength() {
+  return search_model_.search_box()->text().length();
+}
+
 }  // namespace ash
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h
index 84f9817..26176cb 100644
--- a/ash/app_list/app_list_controller_impl.h
+++ b/ash/app_list/app_list_controller_impl.h
@@ -169,6 +169,7 @@
   void LogResultLaunchHistogram(
       app_list::SearchResultLaunchLocation launch_location,
       int suggestion_index) override;
+  void LogSearchAbandonHistogram() override;
   void InvokeSearchResultAction(const std::string& result_id,
                                 int action_index,
                                 int event_flags) override;
@@ -313,6 +314,9 @@
   // Updates which container the launcher window should be in.
   void UpdateLauncherContainer();
 
+// Returns the length of the most recent query.
+  int GetLastQueryLength();
+
   base::string16 last_raw_query_;
 
   mojom::AppListClientPtr client_;
diff --git a/ash/app_list/app_list_metrics.cc b/ash/app_list/app_list_metrics.cc
index 57a1e07..5be6692 100644
--- a/ash/app_list/app_list_metrics.cc
+++ b/ash/app_list/app_list_metrics.cc
@@ -63,6 +63,12 @@
 constexpr char kAppListZeroStateSearchResultRemovalHistogram[] =
     "Apps.ZeroStateSearchResutRemovalDecision";
 
+// The UMA histogram that logs the length of the query when user abandons
+// results of a queried search or recommendations of zero state(zero length
+// query) in launcher UI.
+constexpr char kSearchAbandonQueryLengthHistogram[] =
+    "Apps.AppListSearchAbandonQueryLength";
+
 // The different sources from which a search result is displayed. These values
 // are written to logs.  New enum values can be added, but existing enums must
 // never be renumbered or deleted and reused.
@@ -135,6 +141,12 @@
   }
 }
 
+void RecordSearchAbandonWithQueryLengthHistogram(int query_length) {
+  UMA_HISTOGRAM_EXACT_LINEAR(kSearchAbandonQueryLengthHistogram,
+                             std::min(query_length, kMaxLoggedQueryLength),
+                             kMaxLoggedQueryLength);
+}
+
 void RecordZeroStateSearchResultUserActionHistogram(
     ZeroStateSearchResultUserActionType action) {
   UMA_HISTOGRAM_ENUMERATION(kAppListZeroStateSearchResultUserActionHistogram,
diff --git a/ash/app_list/app_list_metrics.h b/ash/app_list/app_list_metrics.h
index 6bb5ad9e7..b2e65144 100644
--- a/ash/app_list/app_list_metrics.h
+++ b/ash/app_list/app_list_metrics.h
@@ -221,6 +221,9 @@
 void RecordZeroStateSearchResultRemovalHistogram(
     ZeroStateSearchResutRemovalConfirmation removal_decision);
 
+APP_LIST_EXPORT void RecordSearchAbandonWithQueryLengthHistogram(
+    int query_length);
+
 APP_LIST_EXPORT void RecordSearchResultOpenSource(
     const SearchResult* result,
     const AppListModel* model,
diff --git a/ash/app_list/app_list_view_delegate.h b/ash/app_list/app_list_view_delegate.h
index 22f8737..30cb00c 100644
--- a/ash/app_list/app_list_view_delegate.h
+++ b/ash/app_list/app_list_view_delegate.h
@@ -72,6 +72,9 @@
       app_list::SearchResultLaunchLocation launch_location,
       int suggestion_index) = 0;
 
+  // Logs the UMA histogram metrics for user's abandonment of launcher search.
+  virtual void LogSearchAbandonHistogram() = 0;
+
   // Called to invoke a custom action on a result with |result_id|.
   // |action_index| corresponds to the index of an icon in
   // |result.action_icons()|.
diff --git a/ash/app_list/test/app_list_test_view_delegate.h b/ash/app_list/test/app_list_test_view_delegate.h
index 43527ec3..6ee59a7 100644
--- a/ash/app_list/test/app_list_test_view_delegate.h
+++ b/ash/app_list/test/app_list_test_view_delegate.h
@@ -66,6 +66,7 @@
   void LogResultLaunchHistogram(
       app_list::SearchResultLaunchLocation launch_location,
       int suggestion_index) override {}
+  void LogSearchAbandonHistogram() override {}
   void InvokeSearchResultAction(const std::string& result_id,
                                 int action_index,
                                 int event_flags) override {}
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 860684b..6a59675 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -739,8 +739,7 @@
   if (app_list_main_view()->contents_view()->IsShowingEmbeddedAssistantUI())
     Back();
 
-  search_box_view_->ClearSearch();
-  search_box_view_->SetSearchBoxActive(false, ui::ET_UNKNOWN);
+  search_box_view_->ClearSearchAndDeactivateSearchBox();
 }
 
 void AppListView::StartDrag(const gfx::Point& location) {
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc
index d432f1e..ca035652 100644
--- a/ash/app_list/views/contents_view.cc
+++ b/ash/app_list/views/contents_view.cc
@@ -508,8 +508,7 @@
       break;
     }
     case ash::AppListState::kStateSearchResults:
-      GetSearchBoxView()->ClearSearch();
-      GetSearchBoxView()->SetSearchBoxActive(false, ui::ET_UNKNOWN);
+      GetSearchBoxView()->ClearSearchAndDeactivateSearchBox();
       ShowSearchResults(false);
       break;
     case ash::AppListState::kStateEmbeddedAssistant:
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc
index a8a8697..85c82a0 100644
--- a/ash/app_list/views/search_box_view.cc
+++ b/ash/app_list/views/search_box_view.cc
@@ -540,6 +540,16 @@
   ContentsChanged(search_box(), new_query);
 }
 
+void SearchBoxView::ClearSearchAndDeactivateSearchBox() {
+  if (!is_search_box_active())
+    return;
+
+  view_delegate_->LogSearchAbandonHistogram();
+
+  ClearSearch();
+  SetSearchBoxActive(false, ui::ET_UNKNOWN);
+}
+
 bool SearchBoxView::HandleKeyEvent(views::Textfield* sender,
                                    const ui::KeyEvent& key_event) {
   if (key_event.type() == ui::ET_KEY_PRESSED &&
@@ -661,6 +671,7 @@
 void SearchBoxView::ButtonPressed(views::Button* sender,
                                   const ui::Event& event) {
   if (close_button() && sender == close_button()) {
+    view_delegate_->LogSearchAbandonHistogram();
     SetSearchBoxActive(false, ui::ET_UNKNOWN);
   }
   search_box::SearchBoxViewBase::ButtonPressed(sender, event);
diff --git a/ash/app_list/views/search_box_view.h b/ash/app_list/views/search_box_view.h
index 10178eb..9c5576e 100644
--- a/ash/app_list/views/search_box_view.h
+++ b/ash/app_list/views/search_box_view.h
@@ -95,6 +95,9 @@
   // Updates the search box with |new_query| and starts a new search.
   void UpdateQuery(const base::string16& new_query);
 
+  // Clears the search query and de-activate the search box.
+  void ClearSearchAndDeactivateSearchBox();
+
   void set_contents_view(ContentsView* contents_view) {
     contents_view_ = contents_view;
   }
diff --git a/ash/components/fast_ink/fast_ink_view.cc b/ash/components/fast_ink/fast_ink_view.cc
index 6b2a7a4..884707d 100644
--- a/ash/components/fast_ink/fast_ink_view.cc
+++ b/ash/components/fast_ink/fast_ink_view.cc
@@ -467,6 +467,7 @@
       buffer_to_target_transform,
       /*quad_layer_rect=*/output_rect,
       /*visible_quad_layer_rect=*/output_rect,
+      /*rounded_corner_bounds=*/gfx::RRectF(),
       /*clip_rect=*/gfx::Rect(),
       /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
       /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
diff --git a/ash/metrics/histogram_macros.cc b/ash/metrics/histogram_macros.cc
new file mode 100644
index 0000000..bc7c795
--- /dev/null
+++ b/ash/metrics/histogram_macros.cc
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/metrics/histogram_macros.h"
+#include "ash/shell.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
+
+namespace ash {
+
+bool IsInTabletMode() {
+  auto* shell = Shell::Get();
+  return shell && shell->tablet_mode_controller() &&
+         shell->tablet_mode_controller()->IsTabletModeWindowManagerEnabled();
+}
+
+}  // namespace ash
diff --git a/ash/metrics/histogram_macros.h b/ash/metrics/histogram_macros.h
new file mode 100644
index 0000000..7d1b616
--- /dev/null
+++ b/ash/metrics/histogram_macros.h
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_METRICS_HISTOGRAM_MACROS_H_
+#define ASH_METRICS_HISTOGRAM_MACROS_H_
+
+#include "ash/ash_export.h"
+#include "base/metrics/histogram_macros.h"
+
+// Use these instead of UMA_HISTOGRAM_PERCENTAGE if these histogram needs to be
+// recorded separately in tablet/clamshell mode.
+// TODO(oshima): Create a macro which record both that works with presubmit.
+// crbug.com/923159.
+
+#define UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(name, ...) \
+  do {                                                \
+    if (ash::IsInTabletMode())                        \
+      UMA_HISTOGRAM_PERCENTAGE(name, __VA_ARGS__);    \
+  } while (0)
+
+#define UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(name, ...) \
+  do {                                                   \
+    if (!ash::IsInTabletMode())                          \
+      UMA_HISTOGRAM_PERCENTAGE(name, __VA_ARGS__);       \
+  } while (0)
+
+namespace ash {
+
+ASH_EXPORT bool IsInTabletMode();
+
+}  // namespace ash
+
+#endif  // ASH_METRICS_HISTOGRAM_MACROS_H_
diff --git a/ash/metrics/histogram_macros_unittest.cc b/ash/metrics/histogram_macros_unittest.cc
new file mode 100644
index 0000000..4d99c9b
--- /dev/null
+++ b/ash/metrics/histogram_macros_unittest.cc
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/metrics/histogram_macros.h"
+
+#include "ash/test/ash_test_base.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
+#include "base/test/metrics/histogram_tester.h"
+
+namespace ash {
+
+using HistogramMacrosTest = AshTestBase;
+
+TEST_F(HistogramMacrosTest, Basic) {
+  base::HistogramTester histograms;
+  const char* kTablet = "Test.Tablet";
+  const char* kClamshell = "Test.Clamshell";
+
+  UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(kTablet, 1);
+  UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(kClamshell, 1);
+
+  histograms.ExpectTotalCount(kClamshell, 1);
+  histograms.ExpectTotalCount(kTablet, 0);
+
+  TabletModeControllerTestApi().EnterTabletMode();
+
+  UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(kTablet, 1);
+  UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(kClamshell, 1);
+
+  histograms.ExpectTotalCount(kClamshell, 1);
+  histograms.ExpectTotalCount(kTablet, 1);
+}
+
+}  // namespace ash
diff --git a/ash/wm/overview/scoped_overview_animation_settings.cc b/ash/wm/overview/scoped_overview_animation_settings.cc
index 9bb3ea34..f3eb9f07 100644
--- a/ash/wm/overview/scoped_overview_animation_settings.cc
+++ b/ash/wm/overview/scoped_overview_animation_settings.cc
@@ -4,6 +4,7 @@
 
 #include "ash/wm/overview/scoped_overview_animation_settings.h"
 
+#include "ash/metrics/histogram_macros.h"
 #include "base/lazy_instance.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
@@ -96,6 +97,10 @@
   void Report(int value) override {
     UMA_HISTOGRAM_PERCENTAGE("Ash.WindowSelector.AnimationSmoothness.Enter",
                              value);
+    UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(
+        "Ash.Overview.AnimationSmoothness.Enter.Clamshell", value);
+    UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(
+        "Ash.Overview.AnimationSmoothness.Enter.Tablet", value);
   }
 
  private:
@@ -110,6 +115,10 @@
   void Report(int value) override {
     UMA_HISTOGRAM_PERCENTAGE("Ash.WindowSelector.AnimationSmoothness.Exit",
                              value);
+    UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(
+        "Ash.Overview.AnimationSmoothness.Exit.Clamshell", value);
+    UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(
+        "Ash.Overview.AnimationSmoothness.Exit.Table", value);
   }
 
  private:
@@ -124,6 +133,10 @@
   void Report(int value) override {
     UMA_HISTOGRAM_PERCENTAGE("Ash.WindowSelector.AnimationSmoothness.Close",
                              value);
+    UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(
+        "Ash.Overview.AnimationSmoothness.Close.ClamshellMode", value);
+    UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(
+        "Ash.Overview.AnimationSmoothness.Close.TabletMode", value);
   }
 
  private:
diff --git a/ash/ws/window_service_delegate_impl_unittest.cc b/ash/ws/window_service_delegate_impl_unittest.cc
index 6c06e1b..398cabf 100644
--- a/ash/ws/window_service_delegate_impl_unittest.cc
+++ b/ash/ws/window_service_delegate_impl_unittest.cc
@@ -241,6 +241,27 @@
   GetEventGenerator()->ReleaseLeftButton();
 }
 
+TEST_F(WindowServiceDelegateImplTest, NestedWindowMoveIsNotAllowed) {
+  GetWindowTreeTestHelper()->window_tree()->PerformWindowMove(
+      21, GetTopLevelWindowId(), ws::mojom::MoveLoopSource::MOUSE, gfx::Point(),
+      HTCAPTION);
+  EXPECT_TRUE(event_handler()->is_drag_in_progress());
+  GetWindowTreeClientChanges()->clear();
+
+  // Intentionally invokes PerformWindowMove to make sure it does not break
+  // anything.
+  GetWindowTreeTestHelper()->window_tree()->PerformWindowMove(
+      22, GetTopLevelWindowId(), ws::mojom::MoveLoopSource::TOUCH, gfx::Point(),
+      HTCAPTION);
+  EXPECT_TRUE(ContainsChange(*GetWindowTreeClientChanges(),
+                             "ChangeCompleted id=22 success=false"));
+
+  GetWindowTreeClientChanges()->clear();
+  GetEventGenerator()->ReleaseLeftButton();
+  EXPECT_TRUE(ContainsChange(*GetWindowTreeClientChanges(),
+                             "ChangeCompleted id=21 success=true"));
+}
+
 TEST_F(WindowServiceDelegateImplTest, SetWindowResizeShadow) {
   ResizeShadowController* controller = Shell::Get()->resize_shadow_controller();
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index a9a84ad..a2b1e0a 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2992,9 +2992,9 @@
 
     deps = [
       ":jni_java",
-      "//third_party/android_deps:android_support_annotations_java",
-      "//third_party/android_deps:android_support_multidex_java",
       "//third_party/android_deps:android_support_v4_java",
+      "//third_party/android_deps:com_android_support_multidex_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
       "//third_party/jsr-305:jsr_305_javalib",
     ]
 
@@ -3166,8 +3166,8 @@
       ":base_java",
       ":jni_java",
       "//testing/android/reporter:reporter_java",
-      "//third_party/android_deps:android_support_annotations_java",
-      "//third_party/android_deps:android_support_compat_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_compat_java",
       "//third_party/android_support_test_runner:exposed_instrumentation_api_publish_java",
       "//third_party/android_support_test_runner:rules_java",
       "//third_party/android_support_test_runner:runner_java",
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index e334ed0..7887a60 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -462,7 +462,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//testing/android/native_test:native_main_runner_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
       "//third_party/jsr-305:jsr_305_javalib",
     ]
     srcjar_deps = [ ":test_support_java_aidl" ]
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index ec0db871..c2ef945 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -68,6 +68,10 @@
 #include "base/test/fontconfig_util_linux.h"
 #endif
 
+#if defined(OS_FUCHSIA)
+#include "base/base_paths_fuchsia.h"
+#endif
+
 namespace base {
 
 namespace {
@@ -151,12 +155,25 @@
 #if defined(OS_ANDROID)
   InitAndroidTestLogging();
 #else
+
+  FilePath log_filename;
   FilePath exe;
   PathService::Get(FILE_EXE, &exe);
-  FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
+
+#if defined(OS_FUCHSIA)
+  // Write logfiles to /data, because the default log location alongside the
+  // executable (/pkg) is read-only.
+  FilePath data_dir;
+  PathService::Get(DIR_APP_DATA, &data_dir);
+  log_filename = data_dir.Append(exe.BaseName())
+                     .ReplaceExtension(FILE_PATH_LITERAL("log"));
+#else
+  log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
+#endif  // defined(OS_FUCHSIA)
+
   logging::LoggingSettings settings;
-  settings.logging_dest = logging::LOG_TO_ALL;
   settings.log_file = log_filename.value().c_str();
+  settings.logging_dest = logging::LOG_TO_ALL;
   settings.delete_old = logging::DELETE_OLD_LOG_FILE;
   logging::InitLogging(settings);
   // We want process and thread IDs because we may have multiple processes.
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 25f35a53..b9904c8 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -139,6 +139,9 @@
 class DWriteFontLookupTableBuilder;
 class GpuProcessTransportFactory;
 class NestedMessagePumpAndroid;
+class RTCVideoDecoder;
+class RTCVideoDecoderAdapter;
+class RTCVideoEncoder;
 class SandboxHostLinux;
 class ScopedAllowWaitForDebugURL;
 class ServiceWorkerContextClient;
@@ -441,6 +444,9 @@
   friend class base::ScopedAllowThreadRecallForStackSamplingProfiler;
   friend class base::StackSamplingProfiler;
   friend class content::DesktopCaptureDevice;
+  friend class content::RTCVideoDecoder;
+  friend class content::RTCVideoDecoderAdapter;
+  friend class content::RTCVideoEncoder;
   friend class content::SandboxHostLinux;
   friend class content::ScopedAllowWaitForDebugURL;
   friend class content::SynchronousCompositor;
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc
index 8f2b2da..b7e30da0 100644
--- a/base/win/windows_version.cc
+++ b/base/win/windows_version.cc
@@ -57,9 +57,12 @@
 }
 
 const _SYSTEM_INFO& GetSystemInfoStorage() {
-  static _SYSTEM_INFO system_info = {};
-  ::GetNativeSystemInfo(&system_info);
-  return system_info;
+  static const NoDestructor<_SYSTEM_INFO> system_info([] {
+    _SYSTEM_INFO info = {};
+    ::GetNativeSystemInfo(&info);
+    return info;
+  }());
+  return *system_info;
 }
 
 }  // namespace
diff --git a/cc/PRESUBMIT.py b/cc/PRESUBMIT.py
index 89f5675..0b6761a2 100644
--- a/cc/PRESUBMIT.py
+++ b/cc/PRESUBMIT.py
@@ -275,6 +275,27 @@
   else:
     return []
 
+def CheckForDisallowMacros(input_api, output_api, white_list=CC_SOURCE_FILES, black_list=None):
+  black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST)
+  source_file_filter = lambda x: input_api.FilterSourceFile(x, white_list, black_list)
+
+  disallow_macro_files = []
+
+  for f in input_api.AffectedSourceFiles(source_file_filter):
+    contents = input_api.ReadFile(f, 'rb')
+    # DISALLOW macros are not allowed, use deleted constructors instead.
+    if re.search(r"\bDISALLOW_COPY\(", contents) or \
+       re.search(r"\bDISALLOW_ASSIGN\(", contents) or \
+       re.search(r"\bDISALLOW_COPY_AND_ASSIGN\(", contents) or \
+       re.search(r"\bDISALLOW_IMPLICIT_CONSTRUCTORS\(", contents):
+      disallow_macro_files.append(f.LocalPath())
+
+  if disallow_macro_files:
+    return [output_api.PresubmitError(
+      'The following files use DISALLOW* macros. In cc, please use deleted constructors/operators instead.',
+      items=disallow_macro_files)]
+  return []
+
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results += CheckAsserts(input_api, output_api)
@@ -286,4 +307,5 @@
   results += CheckNamespace(input_api, output_api)
   results += CheckForUseOfWrongClock(input_api, output_api)
   results += FindUselessIfdefs(input_api, output_api)
+  results += CheckForDisallowMacros(input_api, output_api)
   return results
diff --git a/cc/animation/animation.h b/cc/animation/animation.h
index a4033d4..feb3302 100644
--- a/cc/animation/animation.h
+++ b/cc/animation/animation.h
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include <memory>
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "cc/animation/animation_curve.h"
@@ -43,6 +42,9 @@
   static scoped_refptr<Animation> Create(int id);
   virtual scoped_refptr<Animation> CreateImplInstance() const;
 
+  Animation(const Animation&) = delete;
+  Animation& operator=(const Animation&) = delete;
+
   int id() const { return id_; }
   typedef size_t KeyframeEffectId;
   ElementId element_id_of_keyframe_effect(
@@ -168,8 +170,6 @@
   KeyframeEffects keyframe_effects_;
 
   int ticking_keyframe_effects_count;
-
-  DISALLOW_COPY_AND_ASSIGN(Animation);
 };
 
 }  // namespace cc
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 96010f94c..33c4bc6 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 70a33e85..7473db7e 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -9,7 +9,6 @@
 #include <unordered_map>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
@@ -56,8 +55,12 @@
   static std::unique_ptr<AnimationHost> CreateMainInstance();
   static std::unique_ptr<AnimationHost> CreateForTesting(
       ThreadInstance thread_instance);
+
+  AnimationHost(const AnimationHost&) = delete;
   ~AnimationHost() override;
 
+  AnimationHost& operator=(const AnimationHost&) = delete;
+
   void AddAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
   void RemoveAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
   AnimationTimeline* GetTimelineById(int timeline_id) const;
@@ -239,8 +242,6 @@
   bool next_frame_has_pending_raf_ = false;
 
   base::WeakPtrFactory<AnimationHost> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(AnimationHost);
 };
 
 }  // namespace cc
diff --git a/cc/animation/animation_id_provider.h b/cc/animation/animation_id_provider.h
index 62823be..cb7a84b 100644
--- a/cc/animation/animation_id_provider.h
+++ b/cc/animation/animation_id_provider.h
@@ -5,21 +5,19 @@
 #ifndef CC_ANIMATION_ANIMATION_ID_PROVIDER_H_
 #define CC_ANIMATION_ANIMATION_ID_PROVIDER_H_
 
-#include "base/macros.h"
 #include "cc/animation/animation_export.h"
 
 namespace cc {
 
 class CC_ANIMATION_EXPORT AnimationIdProvider {
  public:
+  AnimationIdProvider() = delete;
+
   // These functions each return monotonically increasing values.
   static int NextKeyframeModelId();
   static int NextGroupId();
   static int NextTimelineId();
   static int NextAnimationId();
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(AnimationIdProvider);
 };
 
 }  // namespace cc
diff --git a/cc/animation/animation_timeline.h b/cc/animation/animation_timeline.h
index 8b36e621..aebbef7e 100644
--- a/cc/animation/animation_timeline.h
+++ b/cc/animation/animation_timeline.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <unordered_map>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/animation/animation_export.h"
 
@@ -27,6 +26,9 @@
   static scoped_refptr<AnimationTimeline> Create(int id);
   scoped_refptr<AnimationTimeline> CreateImplInstance() const;
 
+  AnimationTimeline(const AnimationTimeline&) = delete;
+  AnimationTimeline& operator=(const AnimationTimeline&) = delete;
+
   int id() const { return id_; }
 
   // Parent AnimationHost.
@@ -73,8 +75,6 @@
   // Impl-only AnimationTimeline has no main thread instance and lives on
   // it's own.
   bool is_impl_only_;
-
-  DISALLOW_COPY_AND_ASSIGN(AnimationTimeline);
 };
 
 }  // namespace cc
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index 7162033a..4926dbce 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -8,7 +8,6 @@
 
 #include <algorithm>
 
-#include "base/macros.h"
 #include "base/numerics/ranges.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/animation/animation_events.h"
diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h
index 5270c95..7e8f124 100644
--- a/cc/animation/element_animations.h
+++ b/cc/animation/element_animations.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "cc/animation/animation_export.h"
@@ -41,6 +40,9 @@
   static scoped_refptr<ElementAnimations> Create(AnimationHost* host,
                                                  ElementId element_id);
 
+  ElementAnimations(const ElementAnimations&) = delete;
+  ElementAnimations& operator=(const ElementAnimations&) = delete;
+
   bool AnimationHostIs(AnimationHost* host) const {
     return animation_host_ == host;
   }
@@ -199,8 +201,6 @@
 
   PropertyAnimationState active_state_;
   PropertyAnimationState pending_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(ElementAnimations);
 };
 
 }  // namespace cc
diff --git a/cc/animation/keyframe_effect.h b/cc/animation/keyframe_effect.h
index c41fef5..500f0bd 100644
--- a/cc/animation/keyframe_effect.h
+++ b/cc/animation/keyframe_effect.h
@@ -5,7 +5,6 @@
 #ifndef CC_ANIMATION_KEYFRAME_EFFECT_H_
 #define CC_ANIMATION_KEYFRAME_EFFECT_H_
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "cc/animation/animation_events.h"
@@ -41,8 +40,11 @@
 class CC_ANIMATION_EXPORT KeyframeEffect {
  public:
   explicit KeyframeEffect(KeyframeEffectId id);
+  KeyframeEffect(const KeyframeEffect&) = delete;
   virtual ~KeyframeEffect();
 
+  KeyframeEffect& operator=(const KeyframeEffect&) = delete;
+
   static std::unique_ptr<KeyframeEffect> Create(KeyframeEffectId id);
   std::unique_ptr<KeyframeEffect> CreateImplInstance() const;
 
@@ -202,8 +204,6 @@
   base::TimeTicks last_tick_time_;
 
   bool needs_push_properties_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframeEffect);
 };
 
 }  // namespace cc
diff --git a/cc/animation/keyframe_model.h b/cc/animation/keyframe_model.h
index cdbb2d5..43a22d88 100644
--- a/cc/animation/keyframe_model.h
+++ b/cc/animation/keyframe_model.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "cc/animation/animation_export.h"
@@ -67,8 +66,11 @@
   std::unique_ptr<KeyframeModel> CreateImplInstance(
       RunState initial_run_state) const;
 
+  KeyframeModel(const KeyframeModel&) = delete;
   virtual ~KeyframeModel();
 
+  KeyframeModel& operator=(const KeyframeModel&) = delete;
+
   int id() const { return id_; }
   int group() const { return group_; }
   int target_property_id() const { return target_property_id_; }
@@ -279,8 +281,6 @@
   // longer affect any elements, and are deleted.
   bool affects_active_elements_;
   bool affects_pending_elements_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframeModel);
 };
 
 }  // namespace cc
diff --git a/cc/animation/keyframed_animation_curve.h b/cc/animation/keyframed_animation_curve.h
index 582a26c2..27e87ba3 100644
--- a/cc/animation/keyframed_animation_curve.h
+++ b/cc/animation/keyframed_animation_curve.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/animation/animation_curve.h"
 #include "cc/animation/animation_export.h"
@@ -19,6 +18,9 @@
 
 class CC_ANIMATION_EXPORT Keyframe {
  public:
+  Keyframe(const Keyframe&) = delete;
+  Keyframe& operator=(const Keyframe&) = delete;
+
   base::TimeDelta Time() const;
   const TimingFunction* timing_function() const {
     return timing_function_.get();
@@ -32,8 +34,6 @@
  private:
   base::TimeDelta time_;
   std::unique_ptr<TimingFunction> timing_function_;
-
-  DISALLOW_COPY_AND_ASSIGN(Keyframe);
 };
 
 class CC_ANIMATION_EXPORT ColorKeyframe : public Keyframe {
@@ -142,8 +142,12 @@
   // It is required that the keyframes be sorted by time.
   static std::unique_ptr<KeyframedColorAnimationCurve> Create();
 
+  KeyframedColorAnimationCurve(const KeyframedColorAnimationCurve&) = delete;
   ~KeyframedColorAnimationCurve() override;
 
+  KeyframedColorAnimationCurve& operator=(const KeyframedColorAnimationCurve&) =
+      delete;
+
   void AddKeyframe(std::unique_ptr<ColorKeyframe> keyframe);
   void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) {
     timing_function_ = std::move(timing_function);
@@ -168,8 +172,6 @@
   std::vector<std::unique_ptr<ColorKeyframe>> keyframes_;
   std::unique_ptr<TimingFunction> timing_function_;
   double scaled_duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframedColorAnimationCurve);
 };
 
 class CC_ANIMATION_EXPORT KeyframedFloatAnimationCurve
@@ -178,8 +180,12 @@
   // It is required that the keyframes be sorted by time.
   static std::unique_ptr<KeyframedFloatAnimationCurve> Create();
 
+  KeyframedFloatAnimationCurve(const KeyframedFloatAnimationCurve&) = delete;
   ~KeyframedFloatAnimationCurve() override;
 
+  KeyframedFloatAnimationCurve& operator=(const KeyframedFloatAnimationCurve&) =
+      delete;
+
   void AddKeyframe(std::unique_ptr<FloatKeyframe> keyframe);
 
   void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) {
@@ -211,8 +217,6 @@
   Keyframes keyframes_;
   std::unique_ptr<TimingFunction> timing_function_;
   double scaled_duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframedFloatAnimationCurve);
 };
 
 class CC_ANIMATION_EXPORT KeyframedTransformAnimationCurve
@@ -221,8 +225,13 @@
   // It is required that the keyframes be sorted by time.
   static std::unique_ptr<KeyframedTransformAnimationCurve> Create();
 
+  KeyframedTransformAnimationCurve(const KeyframedTransformAnimationCurve&) =
+      delete;
   ~KeyframedTransformAnimationCurve() override;
 
+  KeyframedTransformAnimationCurve& operator=(
+      const KeyframedTransformAnimationCurve&) = delete;
+
   void AddKeyframe(std::unique_ptr<TransformKeyframe> keyframe);
   void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) {
     timing_function_ = std::move(timing_function);
@@ -253,8 +262,6 @@
   std::vector<std::unique_ptr<TransformKeyframe>> keyframes_;
   std::unique_ptr<TimingFunction> timing_function_;
   double scaled_duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframedTransformAnimationCurve);
 };
 
 class CC_ANIMATION_EXPORT KeyframedFilterAnimationCurve
@@ -263,8 +270,12 @@
   // It is required that the keyframes be sorted by time.
   static std::unique_ptr<KeyframedFilterAnimationCurve> Create();
 
+  KeyframedFilterAnimationCurve(const KeyframedFilterAnimationCurve&) = delete;
   ~KeyframedFilterAnimationCurve() override;
 
+  KeyframedFilterAnimationCurve& operator=(
+      const KeyframedFilterAnimationCurve&) = delete;
+
   void AddKeyframe(std::unique_ptr<FilterKeyframe> keyframe);
   void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) {
     timing_function_ = std::move(timing_function);
@@ -290,8 +301,6 @@
   std::vector<std::unique_ptr<FilterKeyframe>> keyframes_;
   std::unique_ptr<TimingFunction> timing_function_;
   double scaled_duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframedFilterAnimationCurve);
 };
 
 class CC_ANIMATION_EXPORT KeyframedSizeAnimationCurve
@@ -300,8 +309,12 @@
   // It is required that the keyframes be sorted by time.
   static std::unique_ptr<KeyframedSizeAnimationCurve> Create();
 
+  KeyframedSizeAnimationCurve(const KeyframedSizeAnimationCurve&) = delete;
   ~KeyframedSizeAnimationCurve() override;
 
+  KeyframedSizeAnimationCurve& operator=(const KeyframedSizeAnimationCurve&) =
+      delete;
+
   void AddKeyframe(std::unique_ptr<SizeKeyframe> keyframe);
   void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) {
     timing_function_ = std::move(timing_function);
@@ -326,8 +339,6 @@
   std::vector<std::unique_ptr<SizeKeyframe>> keyframes_;
   std::unique_ptr<TimingFunction> timing_function_;
   double scaled_duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyframedSizeAnimationCurve);
 };
 
 }  // namespace cc
diff --git a/cc/animation/scroll_offset_animation_curve.h b/cc/animation/scroll_offset_animation_curve.h
index 978fe82..fca9af6 100644
--- a/cc/animation/scroll_offset_animation_curve.h
+++ b/cc/animation/scroll_offset_animation_curve.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/animation/animation_curve.h"
 #include "cc/animation/animation_export.h"
@@ -47,8 +46,12 @@
                                          DurationBehavior behavior,
                                          base::TimeDelta delayed_by);
 
+  ScrollOffsetAnimationCurve(const ScrollOffsetAnimationCurve&) = delete;
   ~ScrollOffsetAnimationCurve() override;
 
+  ScrollOffsetAnimationCurve& operator=(const ScrollOffsetAnimationCurve&) =
+      delete;
+
   void SetInitialValue(const gfx::ScrollOffset& initial_value,
                        base::TimeDelta delayed_by = base::TimeDelta());
   bool HasSetInitialValue() const;
@@ -93,8 +96,6 @@
   bool has_set_initial_value_;
 
   static base::Optional<double> animation_duration_for_testing_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimationCurve);
 };
 
 }  // namespace cc
diff --git a/cc/animation/scroll_offset_animations_impl.h b/cc/animation/scroll_offset_animations_impl.h
index e64456e..311f62e 100644
--- a/cc/animation/scroll_offset_animations_impl.h
+++ b/cc/animation/scroll_offset_animations_impl.h
@@ -5,7 +5,6 @@
 #ifndef CC_ANIMATION_SCROLL_OFFSET_ANIMATIONS_IMPL_H_
 #define CC_ANIMATION_SCROLL_OFFSET_ANIMATIONS_IMPL_H_
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/animation/scroll_offset_animation_curve.h"
@@ -27,9 +26,12 @@
     : public AnimationDelegate {
  public:
   explicit ScrollOffsetAnimationsImpl(AnimationHost* animation_host);
-
+  ScrollOffsetAnimationsImpl(const ScrollOffsetAnimationsImpl&) = delete;
   ~ScrollOffsetAnimationsImpl() override;
 
+  ScrollOffsetAnimationsImpl& operator=(const ScrollOffsetAnimationsImpl&) =
+      delete;
+
   // |delayed_by| shrinks the duration of the
   // animation. |animation_start_offset| causes us to start the animation
   // partway through.
@@ -78,8 +80,6 @@
   // I.e. only one element can have an impl-only scroll offset animation at
   // any given time.
   scoped_refptr<SingleKeyframeEffectAnimation> scroll_offset_animation_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimationsImpl);
 };
 
 }  // namespace cc
diff --git a/cc/animation/single_keyframe_effect_animation.h b/cc/animation/single_keyframe_effect_animation.h
index 6baeb76..474250c 100644
--- a/cc/animation/single_keyframe_effect_animation.h
+++ b/cc/animation/single_keyframe_effect_animation.h
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include <memory>
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "cc/animation/animation.h"
@@ -37,6 +36,10 @@
   static scoped_refptr<SingleKeyframeEffectAnimation> Create(int id);
   scoped_refptr<Animation> CreateImplInstance() const override;
 
+  SingleKeyframeEffectAnimation(const SingleKeyframeEffectAnimation&) = delete;
+  SingleKeyframeEffectAnimation& operator=(
+      const SingleKeyframeEffectAnimation&) = delete;
+
   ElementId element_id() const;
 
   void AttachElement(ElementId element_id);
@@ -64,8 +67,6 @@
                                          std::unique_ptr<KeyframeEffect>);
 
   ~SingleKeyframeEffectAnimation() override;
-
-  DISALLOW_COPY_AND_ASSIGN(SingleKeyframeEffectAnimation);
 };
 
 }  // namespace cc
diff --git a/cc/animation/timing_function.h b/cc/animation/timing_function.h
index f5dc7f89..77969ac4 100644
--- a/cc/animation/timing_function.h
+++ b/cc/animation/timing_function.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/animation/animation_export.h"
 #include "ui/gfx/geometry/cubic_bezier.h"
 
@@ -18,6 +17,8 @@
  public:
   virtual ~TimingFunction();
 
+  TimingFunction& operator=(const TimingFunction&) = delete;
+
   // Note that LINEAR is a nullptr TimingFunction (for now).
   enum class Type { LINEAR, CUBIC_BEZIER, STEPS, FRAMES };
 
@@ -28,8 +29,6 @@
 
  protected:
   TimingFunction();
-
-  DISALLOW_ASSIGN(TimingFunction);
 };
 
 class CC_ANIMATION_EXPORT CubicBezierTimingFunction : public TimingFunction {
@@ -44,6 +43,9 @@
                                                            double y2);
   ~CubicBezierTimingFunction() override;
 
+  CubicBezierTimingFunction& operator=(const CubicBezierTimingFunction&) =
+      delete;
+
   // TimingFunction implementation.
   Type GetType() const override;
   double GetValue(double time) const override;
@@ -62,8 +64,6 @@
 
   gfx::CubicBezier bezier_;
   EaseType ease_type_;
-
-  DISALLOW_ASSIGN(CubicBezierTimingFunction);
 };
 
 class CC_ANIMATION_EXPORT StepsTimingFunction : public TimingFunction {
@@ -77,6 +77,8 @@
       StepPosition step_position);
   ~StepsTimingFunction() override;
 
+  StepsTimingFunction& operator=(const StepsTimingFunction&) = delete;
+
   // TimingFunction implementation.
   Type GetType() const override;
   double GetValue(double t) const override;
@@ -94,8 +96,6 @@
 
   int steps_;
   StepPosition step_position_;
-
-  DISALLOW_ASSIGN(StepsTimingFunction);
 };
 
 class CC_ANIMATION_EXPORT FramesTimingFunction : public TimingFunction {
@@ -103,6 +103,8 @@
   static std::unique_ptr<FramesTimingFunction> Create(int frames);
   ~FramesTimingFunction() override;
 
+  FramesTimingFunction& operator=(const FramesTimingFunction&) = delete;
+
   // TimingFunction implementation.
   Type GetType() const override;
   double GetValue(double t) const override;
@@ -116,8 +118,6 @@
   explicit FramesTimingFunction(int frames);
 
   int frames_;
-
-  DISALLOW_ASSIGN(FramesTimingFunction);
 };
 
 }  // namespace cc
diff --git a/cc/animation/transform_operations.h b/cc/animation/transform_operations.h
index 4a6706d7..f8e89ca 100644
--- a/cc/animation/transform_operations.h
+++ b/cc/animation/transform_operations.h
@@ -11,7 +11,6 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "cc/animation/animation_export.h"
 #include "cc/animation/transform_operation.h"
 #include "ui/gfx/transform.h"
diff --git a/cc/base/delayed_unique_notifier.h b/cc/base/delayed_unique_notifier.h
index 4a7486e0..1666987 100644
--- a/cc/base/delayed_unique_notifier.h
+++ b/cc/base/delayed_unique_notifier.h
@@ -6,7 +6,6 @@
 #define CC_BASE_DELAYED_UNIQUE_NOTIFIER_H_
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "cc/base/base_export.h"
 
@@ -23,11 +22,14 @@
   DelayedUniqueNotifier(base::SequencedTaskRunner* task_runner,
                         base::RepeatingClosure closure,
                         const base::TimeDelta& delay);
+  DelayedUniqueNotifier(const DelayedUniqueNotifier&) = delete;
 
   // Destroying the notifier will ensure that no further notifications will
   // happen from this class.
   virtual ~DelayedUniqueNotifier();
 
+  DelayedUniqueNotifier& operator=(const DelayedUniqueNotifier&) = delete;
+
   // Schedule a notification to be run. If another notification is already
   // pending, then it will happen in (at least) given delay from now. That is,
   // if delay is 16ms and a notification has been scheduled 10ms ago (ie, it
@@ -66,8 +68,6 @@
   bool notification_pending_;
 
   base::WeakPtrFactory<DelayedUniqueNotifier> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(DelayedUniqueNotifier);
 };
 
 }  // namespace cc
diff --git a/cc/base/devtools_instrumentation.h b/cc/base/devtools_instrumentation.h
index 0697422..56077e04 100644
--- a/cc/base/devtools_instrumentation.h
+++ b/cc/base/devtools_instrumentation.h
@@ -9,7 +9,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
@@ -53,14 +52,15 @@
     TRACE_EVENT_BEGIN1(internal::CategoryName::kTimeline, event_name_,
                        internal::kLayerId, layer_id);
   }
+  ScopedLayerTask(const ScopedLayerTask&) = delete;
   ~ScopedLayerTask() {
     TRACE_EVENT_END0(internal::CategoryName::kTimeline, event_name_);
   }
 
+  ScopedLayerTask& operator=(const ScopedLayerTask&) = delete;
+
  private:
   const char* event_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedLayerTask);
 };
 
 class CC_BASE_EXPORT ScopedImageDecodeTask {
@@ -71,13 +71,15 @@
   ScopedImageDecodeTask(const void* image_ptr,
                         DecodeType decode_type,
                         TaskType task_type);
+  ScopedImageDecodeTask(const ScopedImageDecodeTask&) = delete;
   ~ScopedImageDecodeTask();
 
+  ScopedImageDecodeTask& operator=(const ScopedImageDecodeTask&) = delete;
+
  private:
   const DecodeType decode_type_;
   const TaskType task_type_;
   const base::TimeTicks start_time_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedImageDecodeTask);
 };
 
 class CC_BASE_EXPORT ScopedLayerTreeTask {
@@ -90,14 +92,15 @@
                        internal::kLayerId, layer_id, internal::kLayerTreeId,
                        layer_tree_host_id);
   }
+  ScopedLayerTreeTask(const ScopedLayerTreeTask&) = delete;
   ~ScopedLayerTreeTask() {
     TRACE_EVENT_END0(internal::CategoryName::kTimeline, event_name_);
   }
 
+  ScopedLayerTreeTask& operator=(const ScopedLayerTreeTask&) = delete;
+
  private:
   const char* event_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedLayerTreeTask);
 };
 
 struct CC_BASE_EXPORT ScopedCommitTrace {
@@ -107,13 +110,13 @@
                        internal::kCompositeLayers, internal::kLayerTreeId,
                        layer_tree_host_id);
   }
+  ScopedCommitTrace(const ScopedCommitTrace&) = delete;
   ~ScopedCommitTrace() {
     TRACE_EVENT_END0(internal::CategoryName::kTimeline,
                      internal::kCompositeLayers);
   }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedCommitTrace);
+  ScopedCommitTrace& operator=(const ScopedCommitTrace&) = delete;
 };
 
 struct CC_BASE_EXPORT ScopedLayerObjectTracker
@@ -124,9 +127,8 @@
             TraceScopedTrackableObject<int, internal::CategoryName::kTimeline>(
                 internal::kLayerId,
                 layer_id) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedLayerObjectTracker);
+  ScopedLayerObjectTracker(const ScopedLayerObjectTracker&) = delete;
+  ScopedLayerObjectTracker& operator=(const ScopedLayerObjectTracker&) = delete;
 };
 
 inline void CC_BASE_EXPORT DidActivateLayerTree(int layer_tree_host_id,
diff --git a/cc/base/histograms.h b/cc/base/histograms.h
index dd88f8c0..d4f8a23 100644
--- a/cc/base/histograms.h
+++ b/cc/base/histograms.h
@@ -6,7 +6,6 @@
 #define CC_BASE_HISTOGRAMS_H_
 
 #include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_math.h"
@@ -92,6 +91,11 @@
 
 class CC_BASE_EXPORT ScopedUMAHistogramAreaTimerBase {
  public:
+  ScopedUMAHistogramAreaTimerBase(const ScopedUMAHistogramAreaTimerBase&) =
+      delete;
+  ScopedUMAHistogramAreaTimerBase& operator=(
+      const ScopedUMAHistogramAreaTimerBase&) = delete;
+
   void AddArea(const base::CheckedNumeric<int>& area) { area_ += area; }
   void SetArea(const base::CheckedNumeric<int>& area) { area_ = area; }
 
@@ -115,7 +119,6 @@
   base::CheckedNumeric<int> area_;
 
   friend class ScopedUMAHistogramAreaTimerBaseTest;
-  DISALLOW_COPY_AND_ASSIGN(ScopedUMAHistogramAreaTimerBase);
 };
 
 }  // namespace cc
diff --git a/cc/base/list_container.h b/cc/base/list_container.h
index 0c20831..2c480e6 100644
--- a/cc/base/list_container.h
+++ b/cc/base/list_container.h
@@ -10,7 +10,6 @@
 #include <memory>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "cc/base/list_container_helper.h"
 
 namespace cc {
@@ -35,6 +34,7 @@
       : helper_(max_alignment,
                 max_size_for_derived_class,
                 num_of_elements_to_reserve_for) {}
+  ListContainer(const ListContainer&) = delete;
 
   ~ListContainer() {
     for (Iterator i = begin(); i != end(); ++i) {
@@ -42,6 +42,8 @@
     }
   }
 
+  ListContainer& operator=(const ListContainer&) = delete;
+
   class Iterator;
   class ConstIterator;
   class ReverseIterator;
@@ -358,8 +360,6 @@
 
  private:
   ListContainerHelper helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(ListContainer);
 };
 
 }  // namespace cc
diff --git a/cc/base/list_container_helper.cc b/cc/base/list_container_helper.cc
index 380ad3d..3a4c0b6 100644
--- a/cc/base/list_container_helper.cc
+++ b/cc/base/list_container_helper.cc
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/aligned_memory.h"
 
 namespace {
@@ -30,6 +29,9 @@
   // This class holds the raw memory chunk, as well as information about its
   // size and availability.
   struct InnerList {
+    InnerList(const InnerList&) = delete;
+    InnerList& operator=(const InnerList&) = delete;
+
     std::unique_ptr<char[], base::AlignedFreeDeleter> data;
     // The number of elements in total the memory can hold. The difference
     // between capacity and size is the how many more elements this list can
@@ -99,9 +101,6 @@
     char* End() const { return data.get() + size * step; }
     char* LastElement() const { return data.get() + (size - 1) * step; }
     char* ElementAt(size_t index) const { return data.get() + index * step; }
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(InnerList);
   };
 
   CharAllocator(size_t alignment, size_t element_size, size_t element_count)
@@ -119,8 +118,11 @@
     last_list_ = storage_[last_list_index_].get();
   }
 
+  CharAllocator(const CharAllocator&) = delete;
   ~CharAllocator() = default;
 
+  CharAllocator& operator=(const CharAllocator&) = delete;
+
   void* Allocate() {
     if (last_list_->IsFull()) {
       // Only allocate a new list if there isn't a spare one still there from
@@ -261,8 +263,6 @@
 
   // This is equivalent to |storage_[last_list_index_]|.
   InnerList* last_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(CharAllocator);
 };
 
 // PositionInCharAllocator
diff --git a/cc/base/list_container_helper.h b/cc/base/list_container_helper.h
index c79cf1f..31658bc 100644
--- a/cc/base/list_container_helper.h
+++ b/cc/base/list_container_helper.h
@@ -9,7 +9,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/base/base_export.h"
 
 namespace cc {
@@ -25,8 +24,11 @@
   explicit ListContainerHelper(size_t alignment,
                                size_t max_size_for_derived_class,
                                size_t num_of_elements_to_reserve_for);
+  ListContainerHelper(const ListContainerHelper&) = delete;
   ~ListContainerHelper();
 
+  ListContainerHelper& operator=(const ListContainerHelper&) = delete;
+
   // This class deals only with char* and void*. It does allocation and passing
   // out raw pointers, as well as memory deallocation when being destroyed.
   class CharAllocator;
@@ -170,8 +172,6 @@
   void* Allocate(size_t alignment, size_t size_of_actual_element_in_bytes);
 
   std::unique_ptr<CharAllocator> data_;
-
-  DISALLOW_COPY_AND_ASSIGN(ListContainerHelper);
 };
 
 }  // namespace cc
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index 2674b83e..c3d8179 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -316,13 +316,16 @@
 class CC_BASE_EXPORT ScopedSubnormalFloatDisabler {
  public:
   ScopedSubnormalFloatDisabler();
+  ScopedSubnormalFloatDisabler(const ScopedSubnormalFloatDisabler&) = delete;
   ~ScopedSubnormalFloatDisabler();
 
- private:
+  ScopedSubnormalFloatDisabler& operator=(const ScopedSubnormalFloatDisabler&) =
+      delete;
+
 #if defined(ARCH_CPU_X86_FAMILY)
+ private:
   unsigned int orig_state_;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(ScopedSubnormalFloatDisabler);
 };
 
 }  // namespace cc
diff --git a/cc/base/rolling_time_delta_history.h b/cc/base/rolling_time_delta_history.h
index f23d583..75832323 100644
--- a/cc/base/rolling_time_delta_history.h
+++ b/cc/base/rolling_time_delta_history.h
@@ -11,7 +11,6 @@
 
 #include "base/containers/circular_deque.h"
 #include "base/containers/flat_map.h"
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/base/base_export.h"
 
@@ -22,9 +21,12 @@
 class CC_BASE_EXPORT RollingTimeDeltaHistory {
  public:
   explicit RollingTimeDeltaHistory(size_t max_size);
+  RollingTimeDeltaHistory(const RollingTimeDeltaHistory&) = delete;
 
   ~RollingTimeDeltaHistory();
 
+  RollingTimeDeltaHistory& operator=(const RollingTimeDeltaHistory&) = delete;
+
   void InsertSample(base::TimeDelta time);
   size_t sample_count() const { return sample_set_.size(); }
 
@@ -44,8 +46,6 @@
   size_t max_size_;
 
   mutable base::flat_map<double, base::TimeDelta> percentile_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(RollingTimeDeltaHistory);
 };
 
 }  // namespace cc
diff --git a/cc/base/rtree.h b/cc/base/rtree.h
index 840eaab..1b3b699 100644
--- a/cc/base/rtree.h
+++ b/cc/base/rtree.h
@@ -42,8 +42,11 @@
 class RTree {
  public:
   RTree();
+  RTree(const RTree&) = delete;
   ~RTree();
 
+  RTree& operator=(const RTree&) = delete;
+
   // Constructs the rtree from a given container of gfx::Rects. Queries using
   // Search will then return indices into this container.
   template <typename Container>
@@ -129,8 +132,6 @@
   size_t num_data_elements_ = 0u;
   Branch<T> root_;
   std::vector<Node<T>> nodes_;
-
-  DISALLOW_COPY_AND_ASSIGN(RTree);
 };
 
 template <typename T>
diff --git a/cc/base/unique_notifier.h b/cc/base/unique_notifier.h
index ff129c8b..ad2172b4 100644
--- a/cc/base/unique_notifier.h
+++ b/cc/base/unique_notifier.h
@@ -6,7 +6,6 @@
 #define CC_BASE_UNIQUE_NOTIFIER_H_
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "cc/base/base_export.h"
 
@@ -23,11 +22,14 @@
   // Configure this notifier to issue the |closure| notification when scheduled.
   UniqueNotifier(base::SequencedTaskRunner* task_runner,
                  base::RepeatingClosure closure);
+  UniqueNotifier(const UniqueNotifier&) = delete;
 
   // Destroying the notifier will ensure that no further notifications will
   // happen from this class.
   ~UniqueNotifier();
 
+  UniqueNotifier& operator=(const UniqueNotifier&) = delete;
+
   // Schedule a notification to be run. If another notification is already
   // pending, then only one notification will take place.
   void Schedule();
@@ -47,8 +49,6 @@
   bool notification_pending_;
 
   base::WeakPtrFactory<UniqueNotifier> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(UniqueNotifier);
 };
 
 }  // namespace cc
diff --git a/cc/benchmarks/benchmark_instrumentation.h b/cc/benchmarks/benchmark_instrumentation.h
index d946c6e6..d2bc0627d 100644
--- a/cc/benchmarks/benchmark_instrumentation.h
+++ b/cc/benchmarks/benchmark_instrumentation.h
@@ -5,7 +5,6 @@
 #ifndef CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_
 #define CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_
 
-#include "base/macros.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/cc_export.h"
 #include "cc/debug/rendering_stats.h"
@@ -38,14 +37,15 @@
     TRACE_EVENT_BEGIN1(internal::Category(), event_name_,
                        internal::kBeginFrameId, begin_frame_id);
   }
+  ScopedBeginFrameTask(const ScopedBeginFrameTask&) = delete;
   ~ScopedBeginFrameTask() {
     TRACE_EVENT_END0(internal::Category(), event_name_);
   }
 
+  ScopedBeginFrameTask& operator=(const ScopedBeginFrameTask&) = delete;
+
  private:
   const char* event_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedBeginFrameTask);
 };
 
 void IssueImplThreadRenderingStatsEvent(const RenderingStats& stats);
diff --git a/cc/benchmarks/micro_benchmark_controller.h b/cc/benchmarks/micro_benchmark_controller.h
index e5eb7b27..ab5ce66f 100644
--- a/cc/benchmarks/micro_benchmark_controller.h
+++ b/cc/benchmarks/micro_benchmark_controller.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "cc/benchmarks/micro_benchmark.h"
 
 namespace base {
@@ -24,8 +23,11 @@
 class CC_EXPORT MicroBenchmarkController {
  public:
   explicit MicroBenchmarkController(LayerTreeHost* host);
+  MicroBenchmarkController(const MicroBenchmarkController&) = delete;
   ~MicroBenchmarkController();
 
+  MicroBenchmarkController& operator=(const MicroBenchmarkController&) = delete;
+
   void DidUpdateLayers();
 
   // Returns the id of the benchmark on success, 0 otherwise.
@@ -45,8 +47,6 @@
   std::vector<std::unique_ptr<MicroBenchmark>> benchmarks_;
   static int next_id_;
   scoped_refptr<base::SingleThreadTaskRunner> main_controller_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkController);
 };
 
 }  // namespace cc
diff --git a/cc/benchmarks/micro_benchmark_controller_impl.h b/cc/benchmarks/micro_benchmark_controller_impl.h
index 7948243..fc1b91c 100644
--- a/cc/benchmarks/micro_benchmark_controller_impl.h
+++ b/cc/benchmarks/micro_benchmark_controller_impl.h
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/benchmarks/micro_benchmark_impl.h"
 
 namespace cc {
@@ -17,8 +16,12 @@
 class CC_EXPORT MicroBenchmarkControllerImpl {
  public:
   explicit MicroBenchmarkControllerImpl(LayerTreeHostImpl* host);
+  MicroBenchmarkControllerImpl(const MicroBenchmarkControllerImpl&) = delete;
   ~MicroBenchmarkControllerImpl();
 
+  MicroBenchmarkControllerImpl& operator=(const MicroBenchmarkControllerImpl&) =
+      delete;
+
   void DidCompleteCommit();
 
   void ScheduleRun(std::unique_ptr<MicroBenchmarkImpl> benchmark);
@@ -28,8 +31,6 @@
 
   LayerTreeHostImpl* host_;
   std::vector<std::unique_ptr<MicroBenchmarkImpl>> benchmarks_;
-
-  DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkControllerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
index cf7f706..6f2da14 100644
--- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
+++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -71,8 +71,7 @@
       settings.image_provider = &image_provider;
 
       raster_source->PlaybackToCanvas(
-          &canvas, gfx::ColorSpace(),
-          raster_source->GetContentSize(contents_scale), content_rect,
+          &canvas, raster_source->GetContentSize(contents_scale), content_rect,
           content_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
           settings);
 
diff --git a/cc/debug/debug_colors.cc b/cc/debug/debug_colors.cc
index eef3fcb7..d8fc52a 100644
--- a/cc/debug/debug_colors.cc
+++ b/cc/debug/debug_colors.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "base/logging.h"
-#include "base/macros.h"
 
 #include "cc/debug/debug_colors.h"
 
diff --git a/cc/debug/debug_colors.h b/cc/debug/debug_colors.h
index d45e0dc..69a73b1 100644
--- a/cc/debug/debug_colors.h
+++ b/cc/debug/debug_colors.h
@@ -6,7 +6,6 @@
 #define CC_DEBUG_DEBUG_COLORS_H_
 
 #include "base/containers/span.h"
-#include "base/macros.h"
 #include "cc/debug/debug_export.h"
 #include "third_party/skia/include/core/SkColor.h"
 
@@ -14,6 +13,8 @@
 
 class CC_DEBUG_EXPORT DebugColors {
  public:
+  DebugColors() = delete;
+
   static SkColor TiledContentLayerBorderColor();
   static int TiledContentLayerBorderWidth(float device_scale_factor);
 
@@ -119,9 +120,6 @@
   static SkColor FPSDisplayTextAndGraphColor();
   static SkColor MemoryDisplayTextColor();
   static SkColor PaintTimeDisplayTextAndGraphColor();
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(DebugColors);
 };
 
 }  // namespace cc
diff --git a/cc/debug/rendering_stats_instrumentation.h b/cc/debug/rendering_stats_instrumentation.h
index 3f656dbe..98ba79b 100644
--- a/cc/debug/rendering_stats_instrumentation.h
+++ b/cc/debug/rendering_stats_instrumentation.h
@@ -9,7 +9,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/synchronization/lock.h"
 #include "cc/debug/rendering_stats.h"
 
@@ -20,8 +19,12 @@
 class CC_DEBUG_EXPORT RenderingStatsInstrumentation {
  public:
   static std::unique_ptr<RenderingStatsInstrumentation> Create();
+  RenderingStatsInstrumentation(const RenderingStatsInstrumentation&) = delete;
   virtual ~RenderingStatsInstrumentation();
 
+  RenderingStatsInstrumentation& operator=(
+      const RenderingStatsInstrumentation&) = delete;
+
   // Return copy of current impl thread rendering stats, and resets the current
   // stats.
   RenderingStats TakeImplThreadRenderingStats();
@@ -58,8 +61,6 @@
   bool record_rendering_stats_;
 
   base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(RenderingStatsInstrumentation);
 };
 
 }  // namespace cc
diff --git a/cc/input/browser_controls_offset_manager.h b/cc/input/browser_controls_offset_manager.h
index 8d0435d2..af00d33 100644
--- a/cc/input/browser_controls_offset_manager.h
+++ b/cc/input/browser_controls_offset_manager.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/input/browser_controls_state.h"
 #include "cc/layers/layer_impl.h"
@@ -27,8 +26,12 @@
       BrowserControlsOffsetManagerClient* client,
       float controls_show_threshold,
       float controls_hide_threshold);
+  BrowserControlsOffsetManager(const BrowserControlsOffsetManager&) = delete;
   virtual ~BrowserControlsOffsetManager();
 
+  BrowserControlsOffsetManager& operator=(const BrowserControlsOffsetManager&) =
+      delete;
+
   // The offset from the window top to the top edge of the controls. Runs from 0
   // (controls fully shown) to negative values (down is positive).
   float ControlsTopOffset() const;
@@ -115,8 +118,6 @@
   // Used to track whether the constraint has changed and we need up reflect
   // the changes to Blink.
   bool constraint_changed_since_commit_;
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserControlsOffsetManager);
 };
 
 }  // namespace cc
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index e8626f8..0aea723a 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/cc_export.h"
 #include "cc/input/event_listener_properties.h"
@@ -59,7 +58,10 @@
 
 class CC_EXPORT InputHandlerClient {
  public:
-  virtual ~InputHandlerClient() {}
+  InputHandlerClient(const InputHandlerClient&) = delete;
+  virtual ~InputHandlerClient() = default;
+
+  InputHandlerClient& operator=(const InputHandlerClient&) = delete;
 
   virtual void WillShutdown() = 0;
   virtual void Animate(base::TimeTicks time) = 0;
@@ -74,10 +76,7 @@
   virtual void DeliverInputForBeginFrame() = 0;
 
  protected:
-  InputHandlerClient() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InputHandlerClient);
+  InputHandlerClient() = default;
 };
 
 // The InputHandler is a way for the embedders to interact with the impl thread
@@ -96,6 +95,9 @@
     LAST_SCROLL_STATUS = SCROLL_UNKNOWN
   };
 
+  InputHandler(const InputHandler&) = delete;
+  InputHandler& operator=(const InputHandler&) = delete;
+
   struct ScrollStatus {
     ScrollStatus()
         : thread(SCROLL_ON_IMPL_THREAD),
@@ -244,11 +246,8 @@
       gfx::Vector2dF* target_offset) const = 0;
 
  protected:
-  InputHandler() {}
-  virtual ~InputHandler() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InputHandler);
+  InputHandler() = default;
+  virtual ~InputHandler() = default;
 };
 
 }  // namespace cc
diff --git a/cc/input/page_scale_animation.h b/cc/input/page_scale_animation.h
index 9d66923e..be4515a 100644
--- a/cc/input/page_scale_animation.h
+++ b/cc/input/page_scale_animation.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/cc_export.h"
 #include "ui/gfx/geometry/cubic_bezier.h"
@@ -51,8 +50,11 @@
       const gfx::SizeF& viewport_size,
       const gfx::SizeF& root_layer_size);
 
+  PageScaleAnimation(const PageScaleAnimation&) = delete;
   ~PageScaleAnimation();
 
+  PageScaleAnimation& operator=(const PageScaleAnimation&) = delete;
+
   // The following methods initialize the animation. Call one of them
   // immediately after construction to set the final scroll and page scale.
 
@@ -123,8 +125,6 @@
   base::TimeDelta duration_;
 
   const gfx::CubicBezier timing_function_;
-
-  DISALLOW_COPY_AND_ASSIGN(PageScaleAnimation);
 };
 
 }  // namespace cc
diff --git a/cc/input/single_scrollbar_animation_controller_thinning.h b/cc/input/single_scrollbar_animation_controller_thinning.h
index 20c06835..80a267d 100644
--- a/cc/input/single_scrollbar_animation_controller_thinning.h
+++ b/cc/input/single_scrollbar_animation_controller_thinning.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
@@ -31,7 +30,12 @@
       ScrollbarAnimationControllerClient* client,
       base::TimeDelta thinning_duration);
 
-  ~SingleScrollbarAnimationControllerThinning() {}
+  SingleScrollbarAnimationControllerThinning(
+      const SingleScrollbarAnimationControllerThinning&) = delete;
+  ~SingleScrollbarAnimationControllerThinning() = default;
+
+  SingleScrollbarAnimationControllerThinning& operator=(
+      const SingleScrollbarAnimationControllerThinning&) = delete;
 
   bool mouse_is_over_scrollbar_thumb() const {
     return mouse_is_over_scrollbar_thumb_;
@@ -96,8 +100,6 @@
   AnimationChange thickness_change_;
 
   base::TimeDelta thinning_duration_;
-
-  DISALLOW_COPY_AND_ASSIGN(SingleScrollbarAnimationControllerThinning);
 };
 
 }  // namespace cc
diff --git a/cc/input/snap_fling_controller.h b/cc/input/snap_fling_controller.h
index eb07106..c5ad511 100644
--- a/cc/input/snap_fling_controller.h
+++ b/cc/input/snap_fling_controller.h
@@ -53,8 +53,11 @@
       SnapFlingClient* client,
       std::unique_ptr<SnapFlingCurve> curve);
 
+  SnapFlingController(const SnapFlingController&) = delete;
   ~SnapFlingController();
 
+  SnapFlingController& operator=(const SnapFlingController&) = delete;
+
   // Returns true if the event should be consumed for snapping and should not be
   // processed further.
   bool FilterEventForSnap(GestureScrollType gesture_scroll_type);
@@ -97,8 +100,6 @@
   SnapFlingClient* client_;
   State state_ = State::kIdle;
   std::unique_ptr<SnapFlingCurve> curve_;
-
-  DISALLOW_COPY_AND_ASSIGN(SnapFlingController);
 };
 
 }  // namespace cc
diff --git a/cc/layers/deadline_policy.h b/cc/layers/deadline_policy.h
index 268ca23..6c3b006 100644
--- a/cc/layers/deadline_policy.h
+++ b/cc/layers/deadline_policy.h
@@ -8,7 +8,6 @@
 #include <cstdint>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/optional.h"
 #include "cc/cc_export.h"
 
diff --git a/cc/layers/heads_up_display_layer.h b/cc/layers/heads_up_display_layer.h
index 2936a975..1337fb6 100644
--- a/cc/layers/heads_up_display_layer.h
+++ b/cc/layers/heads_up_display_layer.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <string>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
@@ -20,6 +19,9 @@
  public:
   static scoped_refptr<HeadsUpDisplayLayer> Create();
 
+  HeadsUpDisplayLayer(const HeadsUpDisplayLayer&) = delete;
+  HeadsUpDisplayLayer& operator=(const HeadsUpDisplayLayer&) = delete;
+
   void UpdateLocationAndSize(const gfx::Size& device_viewport,
                              float device_scale_factor);
 
@@ -36,8 +38,6 @@
   ~HeadsUpDisplayLayer() override;
 
   sk_sp<SkTypeface> typeface_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeadsUpDisplayLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index 6d317814..366013e 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -375,7 +375,8 @@
       {
         ScopedGpuRaster gpu_raster(context_provider);
         viz::ClientResourceProvider::ScopedSkSurface scoped_surface(
-            context_provider->GrContext(), mailbox_texture_id,
+            context_provider->GrContext(),
+            pool_resource.color_space().ToSkColorSpace(), mailbox_texture_id,
             backing->texture_target, pool_resource.size(),
             pool_resource.format(), false /* can_use_lcd_text */,
             0 /* msaa_sample_count */);
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h
index 0315c2c..7f209eb 100644
--- a/cc/layers/heads_up_display_layer_impl.h
+++ b/cc/layers/heads_up_display_layer_impl.h
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "cc/cc_export.h"
@@ -41,8 +40,11 @@
       int id) {
     return base::WrapUnique(new HeadsUpDisplayLayerImpl(tree_impl, id));
   }
+  HeadsUpDisplayLayerImpl(const HeadsUpDisplayLayerImpl&) = delete;
   ~HeadsUpDisplayLayerImpl() override;
 
+  HeadsUpDisplayLayerImpl& operator=(const HeadsUpDisplayLayerImpl&) = delete;
+
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
 
   bool WillDraw(DrawMode draw_mode,
@@ -157,8 +159,6 @@
   std::vector<DebugRect> paint_rects_;
 
   base::TimeTicks time_of_last_graph_update_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeadsUpDisplayLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 0bfbffc..772e066 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -15,7 +15,6 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "cc/base/region.h"
@@ -84,6 +83,9 @@
   // Factory to create a new Layer, with a unique id.
   static scoped_refptr<Layer> Create();
 
+  Layer(const Layer&) = delete;
+  Layer& operator=(const Layer&) = delete;
+
   // Sets an optional client on this layer, that will be called when relevant
   // events happen. The client is a WeakPtr so it can be destroyed without
   // unsetting itself as the client.
@@ -1043,8 +1045,6 @@
   int owner_node_id_;
 
   std::unique_ptr<std::set<Layer*>> clip_children_;
-
-  DISALLOW_COPY_AND_ASSIGN(Layer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index b036dd80..092d9c1 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -139,9 +139,10 @@
                                         bool contents_opaque) const {
   EffectNode* effect_node = GetEffectTree().Node(effect_tree_index_);
   state->SetAll(draw_properties_.target_space_transform, gfx::Rect(bounds()),
-                draw_properties_.visible_layer_rect, draw_properties_.clip_rect,
-                draw_properties_.is_clipped, contents_opaque,
-                draw_properties_.opacity,
+                draw_properties_.visible_layer_rect,
+                draw_properties_.rounded_corner_bounds,
+                draw_properties_.clip_rect, draw_properties_.is_clipped,
+                contents_opaque, draw_properties_.opacity,
                 effect_node->has_render_surface ? SkBlendMode::kSrcOver
                                                 : effect_node->blend_mode,
                 GetSortingContextId());
@@ -163,9 +164,10 @@
 
   EffectNode* effect_node = GetEffectTree().Node(effect_tree_index_);
   state->SetAll(scaled_draw_transform, gfx::Rect(scaled_bounds),
-                scaled_visible_layer_rect, draw_properties().clip_rect,
-                draw_properties().is_clipped, contents_opaque,
-                draw_properties().opacity,
+                scaled_visible_layer_rect,
+                draw_properties().rounded_corner_bounds,
+                draw_properties().clip_rect, draw_properties().is_clipped,
+                contents_opaque, draw_properties().opacity,
                 effect_node->has_render_surface ? SkBlendMode::kSrcOver
                                                 : effect_node->blend_mode,
                 GetSortingContextId());
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index d3f3d6e..8e6dd6c7 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -15,7 +15,6 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "cc/base/region.h"
@@ -79,8 +78,11 @@
     return base::WrapUnique(new LayerImpl(tree_impl, id));
   }
 
+  LayerImpl(const LayerImpl&) = delete;
   virtual ~LayerImpl();
 
+  LayerImpl& operator=(const LayerImpl&) = delete;
+
   int id() const { return layer_id_; }
 
   // Whether this layer is on the active tree, return false if it's on the
@@ -604,8 +606,6 @@
   bool raster_even_if_not_drawn_ : 1;
 
   bool has_transform_node_ : 1;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/nine_patch_generator.h b/cc/layers/nine_patch_generator.h
index f413e4f..afdcb27bf 100644
--- a/cc/layers/nine_patch_generator.h
+++ b/cc/layers/nine_patch_generator.h
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/resources/ui_resource_client.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/cc/layers/nine_patch_layer.h b/cc/layers/nine_patch_layer.h
index ca9fb92..f492e6e 100644
--- a/cc/layers/nine_patch_layer.h
+++ b/cc/layers/nine_patch_layer.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/ui_resource_layer.h"
@@ -20,6 +19,9 @@
  public:
   static scoped_refptr<NinePatchLayer> Create();
 
+  NinePatchLayer(const NinePatchLayer&) = delete;
+  NinePatchLayer& operator=(const NinePatchLayer&) = delete;
+
   void PushPropertiesTo(LayerImpl* layer) override;
 
   // |border| is the space around the center rectangular region in layer space
@@ -60,8 +62,6 @@
   // The occluded region in layer space set by SetLayerOcclusion. It is
   // usually larger than |image_aperture_|.
   gfx::Rect layer_occlusion_;
-
-  DISALLOW_COPY_AND_ASSIGN(NinePatchLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/nine_patch_layer_impl.h b/cc/layers/nine_patch_layer_impl.h
index 5e01501d..d63163d 100644
--- a/cc/layers/nine_patch_layer_impl.h
+++ b/cc/layers/nine_patch_layer_impl.h
@@ -7,7 +7,6 @@
 
 #include <string>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_impl.h"
@@ -29,8 +28,11 @@
                                                     int id) {
     return base::WrapUnique(new NinePatchLayerImpl(tree_impl, id));
   }
+  NinePatchLayerImpl(const NinePatchLayerImpl&) = delete;
   ~NinePatchLayerImpl() override;
 
+  NinePatchLayerImpl& operator=(const NinePatchLayerImpl&) = delete;
+
   // For parameter meanings, see the declaration of NinePatchGenerator.
   void SetLayout(const gfx::Rect& image_aperture,
                  const gfx::Rect& border,
@@ -53,8 +55,6 @@
   const char* LayerTypeAsString() const override;
 
   NinePatchGenerator quad_generator_;
-
-  DISALLOW_COPY_AND_ASSIGN(NinePatchLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/painted_overlay_scrollbar_layer.h b/cc/layers/painted_overlay_scrollbar_layer.h
index 674a7266..931d96c 100644
--- a/cc/layers/painted_overlay_scrollbar_layer.h
+++ b/cc/layers/painted_overlay_scrollbar_layer.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_
 #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/layer.h"
@@ -20,6 +19,9 @@
  public:
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
 
+  PaintedOverlayScrollbarLayer(const PaintedOverlayScrollbarLayer&) = delete;
+  PaintedOverlayScrollbarLayer& operator=(const PaintedOverlayScrollbarLayer&) =
+      delete;
   static scoped_refptr<PaintedOverlayScrollbarLayer> Create(
       std::unique_ptr<Scrollbar> scrollbar,
       ElementId scroll_element_id = ElementId());
@@ -66,8 +68,6 @@
 
   std::unique_ptr<ScopedUIResource> thumb_resource_;
   std::unique_ptr<ScopedUIResource> track_resource_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintedOverlayScrollbarLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/painted_overlay_scrollbar_layer_impl.h b/cc/layers/painted_overlay_scrollbar_layer_impl.h
index 37bdce9..36b2900 100644
--- a/cc/layers/painted_overlay_scrollbar_layer_impl.h
+++ b/cc/layers/painted_overlay_scrollbar_layer_impl.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_IMPL_H_
 #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_IMPL_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/nine_patch_generator.h"
@@ -24,6 +23,10 @@
       int id,
       ScrollbarOrientation orientation,
       bool is_left_side_vertical_scrollbar);
+  PaintedOverlayScrollbarLayerImpl(const PaintedOverlayScrollbarLayerImpl&) =
+      delete;
+  PaintedOverlayScrollbarLayerImpl& operator=(
+      const PaintedOverlayScrollbarLayerImpl&) = delete;
   ~PaintedOverlayScrollbarLayerImpl() override;
 
   // LayerImpl implementation.
@@ -89,8 +92,6 @@
   gfx::Rect aperture_;
 
   NinePatchGenerator quad_generator_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintedOverlayScrollbarLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h
index 6f293bf5..eac5321 100644
--- a/cc/layers/painted_scrollbar_layer.h
+++ b/cc/layers/painted_scrollbar_layer.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_
 #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/layer.h"
@@ -24,6 +23,9 @@
       std::unique_ptr<Scrollbar> scrollbar,
       ElementId element_id = ElementId());
 
+  PaintedScrollbarLayer(const PaintedScrollbarLayer&) = delete;
+  PaintedScrollbarLayer& operator=(const PaintedScrollbarLayer&) = delete;
+
   bool OpacityCanAnimateOnImplThread() const override;
 
   // ScrollbarLayerInterface
@@ -89,8 +91,6 @@
   std::unique_ptr<ScopedUIResource> thumb_resource_;
 
   float thumb_opacity_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintedScrollbarLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/painted_scrollbar_layer_impl.h b/cc/layers/painted_scrollbar_layer_impl.h
index a76b642..ad4daae0 100644
--- a/cc/layers/painted_scrollbar_layer_impl.h
+++ b/cc/layers/painted_scrollbar_layer_impl.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_PAINTED_SCROLLBAR_LAYER_IMPL_H_
 #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_IMPL_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/scrollbar_layer_impl_base.h"
@@ -23,8 +22,12 @@
       ScrollbarOrientation orientation,
       bool is_left_side_vertical_scrollbar,
       bool is_overlay);
+  PaintedScrollbarLayerImpl(const PaintedScrollbarLayerImpl&) = delete;
   ~PaintedScrollbarLayerImpl() override;
 
+  PaintedScrollbarLayerImpl& operator=(const PaintedScrollbarLayerImpl&) =
+      delete;
+
   // LayerImpl implementation.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void PushPropertiesTo(LayerImpl* layer) override;
@@ -87,8 +90,6 @@
   int thumb_length_;
   int track_start_;
   int track_length_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintedScrollbarLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/picture_image_layer.h b/cc/layers/picture_image_layer.h
index c51da8b..b9a424f 100644
--- a/cc/layers/picture_image_layer.h
+++ b/cc/layers/picture_image_layer.h
@@ -7,7 +7,6 @@
 
 #include <stddef.h>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/content_layer_client.h"
 #include "cc/layers/picture_layer.h"
@@ -21,6 +20,9 @@
  public:
   static scoped_refptr<PictureImageLayer> Create();
 
+  PictureImageLayer(const PictureImageLayer&) = delete;
+  PictureImageLayer& operator=(const PictureImageLayer&) = delete;
+
   void SetImage(PaintImage image,
                 const SkMatrix& matrix,
                 bool uses_width_as_height);
@@ -46,8 +48,6 @@
   PaintImage image_;
   SkMatrix matrix_;
   bool uses_width_as_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(PictureImageLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h
index dc53696..48ea872 100644
--- a/cc/layers/picture_layer.h
+++ b/cc/layers/picture_layer.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/base/devtools_instrumentation.h"
 #include "cc/base/invalidation_region.h"
 #include "cc/benchmarks/micro_benchmark_controller.h"
@@ -23,6 +22,9 @@
  public:
   static scoped_refptr<PictureLayer> Create(ContentLayerClient* client);
 
+  PictureLayer(const PictureLayer&) = delete;
+  PictureLayer& operator=(const PictureLayer&) = delete;
+
   void ClearClient();
 
   void SetNearestNeighbor(bool nearest_neighbor);
@@ -98,8 +100,6 @@
 
   int update_source_frame_number_;
   LayerMaskType mask_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(PictureLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 6f85085..82309bd 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -11,7 +11,6 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
@@ -37,8 +36,11 @@
   Create(LayerTreeImpl* tree_impl, int id, Layer::LayerMaskType mask_type) {
     return base::WrapUnique(new PictureLayerImpl(tree_impl, id, mask_type));
   }
+  PictureLayerImpl(const PictureLayerImpl&) = delete;
   ~PictureLayerImpl() override;
 
+  PictureLayerImpl& operator=(const PictureLayerImpl&) = delete;
+
   Layer::LayerMaskType mask_type() const { return mask_type_; }
   void SetLayerMaskType(Layer::LayerMaskType type);
 
@@ -205,8 +207,6 @@
   // of comparing pointers, since objects pointed to are not guaranteed to
   // exist.
   std::vector<PictureLayerTiling*> last_append_quads_tilings_;
-
-  DISALLOW_COPY_AND_ASSIGN(PictureLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc
index 281beab..443203e0a 100644
--- a/cc/layers/picture_layer_impl_perftest.cc
+++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -4,7 +4,6 @@
 
 #include "cc/layers/picture_layer_impl.h"
 
-#include "base/macros.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/lap_timer.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
@@ -50,6 +49,9 @@
                base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
                kTimeCheckInterval) {}
 
+  PictureLayerImplPerfTest(const PictureLayerImplPerfTest&) = delete;
+  PictureLayerImplPerfTest& operator=(const PictureLayerImplPerfTest&) = delete;
+
   void SetUp() override {
     host_impl_.SetVisible(true);
     host_impl_.InitializeFrameSink(layer_tree_frame_sink_.get());
@@ -175,9 +177,6 @@
   FakeLayerTreeHostImpl host_impl_;
   FakePictureLayerImpl* pending_layer_;
   base::LapTimer timer_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PictureLayerImplPerfTest);
 };
 
 TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) {
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 00cbffe..2af18ee 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -12,7 +12,6 @@
 #include <utility>
 
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/animation/animation_host.h"
diff --git a/cc/layers/recording_source.h b/cc/layers/recording_source.h
index 7469a11..a67d51b 100644
--- a/cc/layers/recording_source.h
+++ b/cc/layers/recording_source.h
@@ -9,7 +9,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/base/invalidation_region.h"
 #include "cc/cc_export.h"
@@ -36,8 +35,11 @@
   };
 
   RecordingSource();
+  RecordingSource(const RecordingSource&) = delete;
   virtual ~RecordingSource();
 
+  RecordingSource& operator=(const RecordingSource&) = delete;
+
   bool UpdateAndExpandInvalidation(Region* invalidation,
                                    const gfx::Size& layer_size,
                                    const gfx::Rect& new_recorded_viewport);
@@ -82,8 +84,6 @@
   void DetermineIfSolidColor();
 
   InvalidationRegion invalidation_;
-
-  DISALLOW_COPY_AND_ASSIGN(RecordingSource);
 };
 
 }  // namespace cc
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 6272461..ea81934 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -403,7 +403,7 @@
   viz::SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
   shared_quad_state->SetAll(
-      draw_transform(), content_rect(), content_rect(),
+      draw_transform(), content_rect(), content_rect(), rounded_corner_bounds(),
       draw_properties_.clip_rect, draw_properties_.is_clipped, contents_opaque,
       draw_properties_.draw_opacity, BlendMode(), sorting_context_id);
 
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index b63fc7f..15dd8c9 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -11,7 +11,6 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/draw_mode.h"
 #include "cc/layers/layer_collections.h"
@@ -35,8 +34,11 @@
 class CC_EXPORT RenderSurfaceImpl {
  public:
   RenderSurfaceImpl(LayerTreeImpl* layer_tree_impl, uint64_t stable_id);
+  RenderSurfaceImpl(const RenderSurfaceImpl&) = delete;
   virtual ~RenderSurfaceImpl();
 
+  RenderSurfaceImpl& operator=(const RenderSurfaceImpl&) = delete;
+
   // Returns the RenderSurfaceImpl that this render surface contributes to. Root
   // render surface's render_target is itself.
   RenderSurfaceImpl* render_target();
@@ -252,8 +254,6 @@
   const RenderSurfaceImpl* nearest_occlusion_immune_ancestor_;
 
   std::unique_ptr<DamageTracker> damage_tracker_;
-
-  DISALLOW_COPY_AND_ASSIGN(RenderSurfaceImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/scrollbar_layer_impl_base.h b/cc/layers/scrollbar_layer_impl_base.h
index 8c38e0e..b3cae4b 100644
--- a/cc/layers/scrollbar_layer_impl_base.h
+++ b/cc/layers/scrollbar_layer_impl_base.h
@@ -6,7 +6,6 @@
 #define CC_LAYERS_SCROLLBAR_LAYER_IMPL_BASE_H_
 
 #include "base/containers/flat_set.h"
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/layer.h"
@@ -19,6 +18,9 @@
 
 class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
  public:
+  ScrollbarLayerImplBase(const ScrollbarLayerImplBase&) = delete;
+  ScrollbarLayerImplBase& operator=(const ScrollbarLayerImplBase&) = delete;
+
   ElementId scroll_element_id() const { return scroll_element_id_; }
   void SetScrollElementId(ElementId scroll_element_id);
 
@@ -103,8 +105,6 @@
 
   FRIEND_TEST_ALL_PREFIXES(ScrollbarLayerTest,
                            ScrollElementIdPushedAcrossCommit);
-
-  DISALLOW_COPY_AND_ASSIGN(ScrollbarLayerImplBase);
 };
 
 using ScrollbarSet = base::flat_set<ScrollbarLayerImplBase*>;
diff --git a/cc/layers/scrollbar_layer_interface.h b/cc/layers/scrollbar_layer_interface.h
index a246fca9..661028e4 100644
--- a/cc/layers/scrollbar_layer_interface.h
+++ b/cc/layers/scrollbar_layer_interface.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_SCROLLBAR_LAYER_INTERFACE_H_
 #define CC_LAYERS_SCROLLBAR_LAYER_INTERFACE_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 
@@ -13,14 +12,14 @@
 
 class CC_EXPORT ScrollbarLayerInterface {
  public:
+  ScrollbarLayerInterface(const ScrollbarLayerInterface&) = delete;
+  ScrollbarLayerInterface& operator=(const ScrollbarLayerInterface&) = delete;
+
   virtual void SetScrollElementId(ElementId element_id) = 0;
 
  protected:
   ScrollbarLayerInterface() {}
   virtual ~ScrollbarLayerInterface() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScrollbarLayerInterface);
 };
 
 }  // namespace cc
diff --git a/cc/layers/solid_color_layer.h b/cc/layers/solid_color_layer.h
index 653dd8a..7b97ac046 100644
--- a/cc/layers/solid_color_layer.h
+++ b/cc/layers/solid_color_layer.h
@@ -6,7 +6,6 @@
 #ifndef CC_LAYERS_SOLID_COLOR_LAYER_H_
 #define CC_LAYERS_SOLID_COLOR_LAYER_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
 
@@ -18,6 +17,9 @@
  public:
   static scoped_refptr<SolidColorLayer> Create();
 
+  SolidColorLayer(const SolidColorLayer&) = delete;
+  SolidColorLayer& operator=(const SolidColorLayer&) = delete;
+
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
 
   void SetBackgroundColor(SkColor color) override;
@@ -27,8 +29,6 @@
 
  private:
   ~SolidColorLayer() override;
-
-  DISALLOW_COPY_AND_ASSIGN(SolidColorLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/solid_color_layer_impl.h b/cc/layers/solid_color_layer_impl.h
index 78a35a4..68d1e1a 100644
--- a/cc/layers/solid_color_layer_impl.h
+++ b/cc/layers/solid_color_layer_impl.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_impl.h"
@@ -21,6 +20,9 @@
     return base::WrapUnique(new SolidColorLayerImpl(tree_impl, id));
   }
 
+  SolidColorLayerImpl(const SolidColorLayerImpl&) = delete;
+  SolidColorLayerImpl& operator=(const SolidColorLayerImpl&) = delete;
+
   static void AppendSolidQuads(viz::RenderPass* render_pass,
                                const Occlusion& occlusion_in_layer_space,
                                viz::SharedQuadState* shared_quad_state,
@@ -42,8 +44,6 @@
 
  private:
   const char* LayerTypeAsString() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(SolidColorLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/solid_color_scrollbar_layer.h b/cc/layers/solid_color_scrollbar_layer.h
index 69bcc4f..67c4adb2 100644
--- a/cc/layers/solid_color_scrollbar_layer.h
+++ b/cc/layers/solid_color_scrollbar_layer.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_H_
 #define CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/scrollbar_layer_interface.h"
@@ -24,6 +23,9 @@
       bool is_left_side_vertical_scrollbar,
       ElementId scroll_element_id);
 
+  SolidColorScrollbarLayer(const SolidColorScrollbarLayer&) = delete;
+  SolidColorScrollbarLayer& operator=(const SolidColorScrollbarLayer&) = delete;
+
   // Layer overrides.
   bool OpacityCanAnimateOnImplThread() const override;
 
@@ -63,8 +65,6 @@
   };
 
   SolidColorScrollbarLayerInputs solid_color_scrollbar_layer_inputs_;
-
-  DISALLOW_COPY_AND_ASSIGN(SolidColorScrollbarLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index afe7d8e..0bc24a03 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -6,7 +6,6 @@
 
 #include <stdint.h>
 
-#include "base/macros.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/layers/surface_layer_impl.h"
 #include "cc/trees/layer_tree_host.h"
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h
index 61c7830..9d15812 100644
--- a/cc/layers/surface_layer.h
+++ b/cc/layers/surface_layer.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_SURFACE_LAYER_H_
 #define CC_LAYERS_SURFACE_LAYER_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/deadline_policy.h"
 #include "cc/layers/layer.h"
@@ -27,6 +26,9 @@
   static scoped_refptr<SurfaceLayer> Create();
   static scoped_refptr<SurfaceLayer> Create(UpdateSubmissionStateCB);
 
+  SurfaceLayer(const SurfaceLayer&) = delete;
+  SurfaceLayer& operator=(const SurfaceLayer&) = delete;
+
   void SetSurfaceId(const viz::SurfaceId& surface_id,
                     const DeadlinePolicy& deadline_policy);
   void SetOldestAcceptableFallback(const viz::SurfaceId& surface_id);
@@ -88,8 +90,6 @@
   // TODO(sunxd): consider renaming it to oopif_has_pointer_events_none_ for
   // disambiguation.
   bool has_pointer_events_none_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(SurfaceLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h
index d00a8ba..4daa923 100644
--- a/cc/layers/surface_layer_impl.h
+++ b/cc/layers/surface_layer_impl.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_impl.h"
@@ -38,8 +37,11 @@
         new SurfaceLayerImpl(tree_impl, id, base::BindRepeating([](bool) {})));
   }
 
+  SurfaceLayerImpl(const SurfaceLayerImpl&) = delete;
   ~SurfaceLayerImpl() override;
 
+  SurfaceLayerImpl& operator=(const SurfaceLayerImpl&) = delete;
+
   void SetRange(const viz::SurfaceRange& surface_range,
                 base::Optional<uint32_t> deadline_in_frames);
   const viz::SurfaceRange& range() const { return surface_range_; }
@@ -92,8 +94,6 @@
   bool surface_hit_testable_ = false;
   bool has_pointer_events_none_ = false;
   bool will_draw_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(SurfaceLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h
index b5d59931..dc9bd63 100644
--- a/cc/layers/texture_layer.h
+++ b/cc/layers/texture_layer.h
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
@@ -43,14 +42,21 @@
     class CC_EXPORT MainThreadReference {
      public:
       explicit MainThreadReference(TransferableResourceHolder* holder);
+      MainThreadReference(const MainThreadReference&) = delete;
       ~MainThreadReference();
+
+      MainThreadReference& operator=(const MainThreadReference&) = delete;
+
       TransferableResourceHolder* holder() { return holder_.get(); }
 
      private:
       scoped_refptr<TransferableResourceHolder> holder_;
-      DISALLOW_COPY_AND_ASSIGN(MainThreadReference);
     };
 
+    TransferableResourceHolder(const TransferableResourceHolder&) = delete;
+    TransferableResourceHolder& operator=(const TransferableResourceHolder&) =
+        delete;
+
     const viz::TransferableResource& resource() const { return resource_; }
     void Return(const gpu::SyncToken& sync_token, bool is_lost);
 
@@ -102,13 +108,15 @@
     gpu::SyncToken sync_token_;
     bool is_lost_ = false;
     base::ThreadChecker main_thread_checker_;
-    DISALLOW_COPY_AND_ASSIGN(TransferableResourceHolder);
   };
 
   // Used when mailbox names are specified instead of texture IDs.
   static scoped_refptr<TextureLayer> CreateForMailbox(
       TextureLayerClient* client);
 
+  TextureLayer(const TextureLayer&) = delete;
+  TextureLayer& operator=(const TextureLayer&) = delete;
+
   // Resets the client, which also resets the texture.
   void ClearClient();
 
@@ -215,8 +223,6 @@
   std::vector<viz::SharedBitmapId> to_unregister_bitmap_ids_;
 
   base::WeakPtrFactory<TextureLayer> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(TextureLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h
index 51da8cd..d2ae0db 100644
--- a/cc/layers/texture_layer_impl.h
+++ b/cc/layers/texture_layer_impl.h
@@ -9,7 +9,6 @@
 
 #include "base/callback.h"
 #include "base/containers/flat_map.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_impl.h"
@@ -28,8 +27,11 @@
                                                   int id) {
     return base::WrapUnique(new TextureLayerImpl(tree_impl, id));
   }
+  TextureLayerImpl(const TextureLayerImpl&) = delete;
   ~TextureLayerImpl() override;
 
+  TextureLayerImpl& operator=(const TextureLayerImpl&) = delete;
+
   std::unique_ptr<LayerImpl> CreateLayerImpl(
       LayerTreeImpl* layer_tree_impl) override;
   bool IsSnappedToPixelGridInTarget() override;
@@ -123,8 +125,6 @@
   // As a pending layer, the set of SharedBitmapIds that the active layer should
   // unregister.
   std::vector<viz::SharedBitmapId> to_unregister_bitmap_ids_;
-
-  DISALLOW_COPY_AND_ASSIGN(TextureLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index c85b89e9..64697a6c 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
diff --git a/cc/layers/ui_resource_layer.h b/cc/layers/ui_resource_layer.h
index 57d2f03..529ef85 100644
--- a/cc/layers/ui_resource_layer.h
+++ b/cc/layers/ui_resource_layer.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
 #include "cc/resources/ui_resource_client.h"
@@ -21,6 +20,9 @@
  public:
   static scoped_refptr<UIResourceLayer> Create();
 
+  UIResourceLayer(const UIResourceLayer&) = delete;
+  UIResourceLayer& operator=(const UIResourceLayer&) = delete;
+
   void PushPropertiesTo(LayerImpl* layer) override;
 
   void SetLayerTreeHost(LayerTreeHost* host) override;
@@ -66,8 +68,6 @@
   gfx::PointF uv_top_left_;
   gfx::PointF uv_bottom_right_;
   float vertex_opacity_[4];
-
-  DISALLOW_COPY_AND_ASSIGN(UIResourceLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/ui_resource_layer_impl.h b/cc/layers/ui_resource_layer_impl.h
index 1283a23..f1ad51d0 100644
--- a/cc/layers/ui_resource_layer_impl.h
+++ b/cc/layers/ui_resource_layer_impl.h
@@ -7,7 +7,6 @@
 
 #include <string>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_impl.h"
@@ -31,8 +30,11 @@
                                                      int id) {
     return base::WrapUnique(new UIResourceLayerImpl(tree_impl, id));
   }
+  UIResourceLayerImpl(const UIResourceLayerImpl&) = delete;
   ~UIResourceLayerImpl() override;
 
+  UIResourceLayerImpl& operator=(const UIResourceLayerImpl&) = delete;
+
   void SetUIResourceId(UIResourceId uid);
 
   void SetImageBounds(const gfx::Size& image_bounds);
@@ -68,8 +70,6 @@
 
  private:
   const char* LayerTypeAsString() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(UIResourceLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/video_frame_provider_client_impl.h b/cc/layers/video_frame_provider_client_impl.h
index 6c11f72..2798dd01 100644
--- a/cc/layers/video_frame_provider_client_impl.h
+++ b/cc/layers/video_frame_provider_client_impl.h
@@ -5,7 +5,6 @@
 #ifndef CC_LAYERS_VIDEO_FRAME_PROVIDER_CLIENT_IMPL_H_
 #define CC_LAYERS_VIDEO_FRAME_PROVIDER_CLIENT_IMPL_H_
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
@@ -33,6 +32,10 @@
       VideoFrameProvider* provider,
       VideoFrameControllerClient* client);
 
+  VideoFrameProviderClientImpl(const VideoFrameProviderClientImpl&) = delete;
+  VideoFrameProviderClientImpl& operator=(const VideoFrameProviderClientImpl&) =
+      delete;
+
   VideoLayerImpl* ActiveVideoLayer() const;
   void SetActiveVideoLayer(VideoLayerImpl* video_layer);
 
@@ -82,8 +85,6 @@
   // from returning until the frame controller is done using the frame.
   base::Lock provider_lock_;
   base::ThreadChecker thread_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(VideoFrameProviderClientImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/video_frame_provider_client_impl_unittest.cc b/cc/layers/video_frame_provider_client_impl_unittest.cc
index 32627b8..5d03c67 100644
--- a/cc/layers/video_frame_provider_client_impl_unittest.cc
+++ b/cc/layers/video_frame_provider_client_impl_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "cc/layers/video_frame_provider_client_impl.h"
-#include "base/macros.h"
 #include "cc/layers/video_layer_impl.h"
 #include "cc/test/fake_video_frame_provider.h"
 #include "cc/test/layer_test_common.h"
@@ -40,6 +39,8 @@
                                                    base::TimeDelta())) {
     DebugSetImplThreadAndMainThreadBlocked(impl_.task_runner_provider());
   }
+  VideoFrameProviderClientImplTest(const VideoFrameProviderClientImplTest&) =
+      delete;
 
   ~VideoFrameProviderClientImplTest() override {
     if (!client_impl_->Stopped()) {
@@ -51,6 +52,9 @@
     provider_.SetVideoFrameProviderClient(nullptr);
   }
 
+  VideoFrameProviderClientImplTest& operator=(
+      const VideoFrameProviderClientImplTest&) = delete;
+
   void StartRendering() {
     EXPECT_CALL(*this, AddVideoFrameController(_));
     client_impl_->StartRendering();
@@ -92,9 +96,6 @@
   scoped_refptr<VideoFrameProviderClientImpl> client_impl_;
   VideoLayerImpl* video_layer_impl_;
   scoped_refptr<media::VideoFrame> test_frame_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VideoFrameProviderClientImplTest);
 };
 
 TEST_F(VideoFrameProviderClientImplTest, StartStopRendering) {
diff --git a/cc/layers/video_layer.h b/cc/layers/video_layer.h
index 02919b1..0ae52c8 100644
--- a/cc/layers/video_layer.h
+++ b/cc/layers/video_layer.h
@@ -6,7 +6,6 @@
 #define CC_LAYERS_VIDEO_LAYER_H_
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
 #include "media/base/video_rotation.h"
@@ -24,6 +23,9 @@
   static scoped_refptr<VideoLayer> Create(VideoFrameProvider* provider,
                                           media::VideoRotation video_rotation);
 
+  VideoLayer(const VideoLayer&) = delete;
+  VideoLayer& operator=(const VideoLayer&) = delete;
+
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
 
   bool Update() override;
@@ -40,8 +42,6 @@
   VideoFrameProvider* provider_;
 
   media::VideoRotation video_rotation_;
-
-  DISALLOW_COPY_AND_ASSIGN(VideoLayer);
 };
 
 }  // namespace cc
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index eab1e6a..b76baeb 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -159,8 +159,9 @@
     return;
 
   updater_->AppendQuads(
-      render_pass, frame_, transform, quad_rect, visible_quad_rect, clip_rect(),
-      is_clipped(), contents_opaque(), draw_opacity(), GetSortingContextId());
+      render_pass, frame_, transform, quad_rect, visible_quad_rect,
+      draw_properties().rounded_corner_bounds, clip_rect(), is_clipped(),
+      contents_opaque(), draw_opacity(), GetSortingContextId());
 }
 
 void VideoLayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) {
diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h
index 4b3646b..0f715c7 100644
--- a/cc/layers/video_layer_impl.h
+++ b/cc/layers/video_layer_impl.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_impl.h"
 #include "components/viz/common/resources/release_callback.h"
@@ -31,8 +30,11 @@
       int id,
       VideoFrameProvider* provider,
       media::VideoRotation video_rotation);
+  VideoLayerImpl(const VideoLayerImpl&) = delete;
   ~VideoLayerImpl() override;
 
+  VideoLayerImpl& operator=(const VideoLayerImpl&) = delete;
+
   // LayerImpl implementation.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   bool WillDraw(DrawMode draw_mode,
@@ -63,8 +65,6 @@
   media::VideoRotation video_rotation_;
 
   std::unique_ptr<media::VideoResourceUpdater> updater_;
-
-  DISALLOW_COPY_AND_ASSIGN(VideoLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/layers/viewport.h b/cc/layers/viewport.h
index 275e826..5abe67d 100644
--- a/cc/layers/viewport.h
+++ b/cc/layers/viewport.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/gtest_prod_util.h"
-#include "base/macros.h"
 #include "cc/layers/layer_impl.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
@@ -38,6 +37,9 @@
 
   static std::unique_ptr<Viewport> Create(LayerTreeHostImpl* host_impl);
 
+  Viewport(const Viewport&) = delete;
+  Viewport& operator=(const Viewport&) = delete;
+
   // Differs from scrolling in that only the visual viewport is moved, without
   // affecting the browser controls or outer viewport.
   void Pan(const gfx::Vector2dF& delta);
@@ -103,8 +105,6 @@
   gfx::Vector2d pinch_anchor_adjustment_;
 
   FRIEND_TEST_ALL_PREFIXES(ViewportTest, ShouldAnimateViewport);
-
-  DISALLOW_COPY_AND_ASSIGN(Viewport);
 };
 
 }  // namespace cc
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.h b/cc/mojo_embedder/async_layer_tree_frame_sink.h
index 91bf450..5ed49023 100644
--- a/cc/mojo_embedder/async_layer_tree_frame_sink.h
+++ b/cc/mojo_embedder/async_layer_tree_frame_sink.h
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "cc/mojo_embedder/mojo_embedder_export.h"
@@ -103,9 +102,11 @@
       scoped_refptr<viz::ContextProvider> context_provider,
       scoped_refptr<viz::RasterContextProvider> worker_context_provider,
       InitParams* params);
-
+  AsyncLayerTreeFrameSink(const AsyncLayerTreeFrameSink&) = delete;
   ~AsyncLayerTreeFrameSink() override;
 
+  AsyncLayerTreeFrameSink& operator=(const AsyncLayerTreeFrameSink&) = delete;
+
   const viz::HitTestDataProvider* hit_test_data_provider() const {
     return hit_test_data_provider_.get();
   }
@@ -187,8 +188,6 @@
   // GraphicsPipeline.ClientName.SubmitCompositorFrameAfterBeginFrame
   base::HistogramBase* const submit_begin_frame_histogram_;
   base::WeakPtrFactory<AsyncLayerTreeFrameSink> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncLayerTreeFrameSink);
 };
 
 }  // namespace mojo_embedder
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc b/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
index cc49361e..0a6f1d6c 100644
--- a/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
+++ b/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
@@ -39,8 +39,13 @@
       base::PlatformThreadId* called_thread_id,
       base::RunLoop* run_loop)
       : called_thread_id_(called_thread_id), run_loop_(run_loop) {}
+  ThreadTrackingLayerTreeFrameSinkClient(
+      const ThreadTrackingLayerTreeFrameSinkClient&) = delete;
   ~ThreadTrackingLayerTreeFrameSinkClient() override = default;
 
+  ThreadTrackingLayerTreeFrameSinkClient& operator=(
+      const ThreadTrackingLayerTreeFrameSinkClient&) = delete;
+
   // FakeLayerTreeFrameSinkClient:
   void DidLoseLayerTreeFrameSink() override {
     EXPECT_FALSE(did_lose_layer_tree_frame_sink_called());
@@ -52,8 +57,6 @@
  private:
   base::PlatformThreadId* called_thread_id_;
   base::RunLoop* run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThreadTrackingLayerTreeFrameSinkClient);
 };
 
 TEST(AsyncLayerTreeFrameSinkTest,
@@ -190,7 +193,8 @@
   gfx::Rect rect1(display_rect_);
   shared_quad_state1->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect1,
-      /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1,
+      /*visible_quad_layer_rect=*/rect1,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect1,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad1 =
@@ -211,7 +215,8 @@
   gfx::Rect rect2(display_rect_);
   shared_quad_state2->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect2,
-      /*visible_quad_layer_rect=*/rect2, /*clip_rect=*/rect2,
+      /*visible_quad_layer_rect=*/rect2,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad2 =
@@ -239,7 +244,8 @@
   transform3_0.Translate(-200, -100);
   shared_quad_state3_0->SetAll(
       transform3_0, /*quad_layer_rect=*/rect3_0,
-      /*visible_quad_layer_rect=*/rect3_0, /*clip_rect=*/rect3_0,
+      /*visible_quad_layer_rect=*/rect3_0,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3_0,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad3_0 =
@@ -259,7 +265,8 @@
   gfx::Rect rect3_1(display_rect_);
   shared_quad_state3_1->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect3_1,
-      /*visible_quad_layer_rect=*/rect3_1, /*clip_rect=*/rect3_1,
+      /*visible_quad_layer_rect=*/rect3_1,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3_1,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad3_1 =
@@ -276,7 +283,8 @@
   gfx::Rect rect3_root(display_rect_);
   shared_quad_state3_root->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect3_root,
-      /*visible_quad_layer_rect=*/rect3_root, /*clip_rect=*/rect3_root,
+      /*visible_quad_layer_rect=*/rect3_root,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3_root,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad3_root_1 =
@@ -313,7 +321,8 @@
   gfx::Rect rect1(display_rect_);
   shared_quad_state1->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect1,
-      /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1,
+      /*visible_quad_layer_rect=*/rect1,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect1,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad1 =
@@ -339,7 +348,8 @@
   transform2_0.Translate(-200, -100);
   shared_quad_state2_0->SetAll(
       transform2_0, /*quad_layer_rect=*/rect2_0,
-      /*visible_quad_layer_rect=*/rect2_0, /*clip_rect=*/rect2_0,
+      /*visible_quad_layer_rect=*/rect2_0,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2_0,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad2_0 =
@@ -359,7 +369,8 @@
   gfx::Rect rect2_1(display_rect_);
   shared_quad_state2_1->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect2_1,
-      /*visible_quad_layer_rect=*/rect2_1, /*clip_rect=*/rect2_1,
+      /*visible_quad_layer_rect=*/rect2_1,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2_1,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad2_1 =
@@ -376,7 +387,8 @@
   gfx::Rect rect2_root(display_rect_);
   shared_quad_state2_root->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect2_root,
-      /*visible_quad_layer_rect=*/rect2_root, /*clip_rect=*/rect2_root,
+      /*visible_quad_layer_rect=*/rect2_root,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2_root,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad2_root_1 =
@@ -411,7 +423,8 @@
   gfx::Rect rect3(display_rect_);
   shared_quad_state3->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect3,
-      /*visible_quad_layer_rect=*/rect3, /*clip_rect=*/rect3,
+      /*visible_quad_layer_rect=*/rect3,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad3 =
diff --git a/cc/paint/decode_stashing_image_provider.h b/cc/paint/decode_stashing_image_provider.h
index 99a45d9..e638d03 100644
--- a/cc/paint/decode_stashing_image_provider.h
+++ b/cc/paint/decode_stashing_image_provider.h
@@ -17,8 +17,12 @@
  public:
   // |source_provider| must outlive this class.
   explicit DecodeStashingImageProvider(ImageProvider* source_provider);
+  DecodeStashingImageProvider(const DecodeStashingImageProvider&) = delete;
   ~DecodeStashingImageProvider() override;
 
+  DecodeStashingImageProvider& operator=(const DecodeStashingImageProvider&) =
+      delete;
+
   // ImageProvider implementation.
   ImageProvider::ScopedResult GetRasterContent(
       const DrawImage& draw_image) override;
@@ -30,8 +34,6 @@
  private:
   ImageProvider* source_provider_;
   base::StackVector<ScopedResult, 1> decoded_images_;
-
-  DISALLOW_COPY_AND_ASSIGN(DecodeStashingImageProvider);
 };
 
 }  // namespace cc
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h
index a61ed5c..1eb89208 100644
--- a/cc/paint/display_item_list.h
+++ b/cc/paint/display_item_list.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/rtree.h"
@@ -58,6 +57,8 @@
   enum UsageHint { kTopLevelDisplayItemList, kToBeReleasedAsPaintOpBuffer };
 
   explicit DisplayItemList(UsageHint = kTopLevelDisplayItemList);
+  DisplayItemList(const DisplayItemList&) = delete;
+  DisplayItemList& operator=(const DisplayItemList&) = delete;
 
   void Raster(SkCanvas* canvas, ImageProvider* image_provider = nullptr) const;
 
@@ -247,7 +248,6 @@
 
   friend class base::RefCountedThreadSafe<DisplayItemList>;
   FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, BytesUsed);
-  DISALLOW_COPY_AND_ASSIGN(DisplayItemList);
 };
 
 }  // namespace cc
diff --git a/cc/paint/image_provider.h b/cc/paint/image_provider.h
index 9ec5b3b..6ffd8978 100644
--- a/cc/paint/image_provider.h
+++ b/cc/paint/image_provider.h
@@ -28,9 +28,11 @@
     explicit ScopedResult(DecodedDrawImage image);
     ScopedResult(DecodedDrawImage image, DestructionCallback callback);
     ScopedResult(const PaintRecord* record, DestructionCallback callback);
+    ScopedResult(const ScopedResult&) = delete;
+    ScopedResult(ScopedResult&& other);
     ~ScopedResult();
 
-    ScopedResult(ScopedResult&& other);
+    ScopedResult& operator=(const ScopedResult&) = delete;
     ScopedResult& operator=(ScopedResult&& other);
 
     operator bool() const { return image_ || record_; }
@@ -47,8 +49,6 @@
     DecodedDrawImage image_;
     const PaintRecord* record_ = nullptr;
     DestructionCallback destruction_callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedResult);
   };
 
   virtual ~ImageProvider() {}
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc
index 2ac24c2..3e90ba7 100644
--- a/cc/paint/oop_pixeltest.cc
+++ b/cc/paint/oop_pixeltest.cc
@@ -295,7 +295,8 @@
           SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
     }
     SkImageInfo image_info = SkImageInfo::MakeN32Premul(
-        options.resource_size.width(), options.resource_size.height());
+        options.resource_size.width(), options.resource_size.height(),
+        options.color_space.ToSkColorSpace());
     auto surface = SkSurface::MakeRenderTarget(
         gles2_context_provider_->GrContext(), SkBudgeted::kYes, image_info);
     SkCanvas* canvas = surface->getCanvas();
@@ -307,9 +308,8 @@
     gfx::AxisTransform2d raster_transform(options.post_scale,
                                           options.post_translate);
     raster_source->PlaybackToCanvas(
-        canvas, options.color_space, options.content_size,
-        options.full_raster_rect, options.playback_rect, raster_transform,
-        settings);
+        canvas, options.content_size, options.full_raster_rect,
+        options.playback_rect, raster_transform, settings);
     surface->prepareForExternalIO();
     EXPECT_EQ(gles2_context_provider_->ContextGL()->GetError(),
               static_cast<unsigned>(GL_NO_ERROR));
diff --git a/cc/paint/paint_cache.h b/cc/paint/paint_cache.h
index 3413f43..f4467014 100644
--- a/cc/paint/paint_cache.h
+++ b/cc/paint/paint_cache.h
@@ -50,8 +50,11 @@
 class CC_PAINT_EXPORT ClientPaintCache {
  public:
   explicit ClientPaintCache(size_t max_budget_bytes);
+  ClientPaintCache(const ClientPaintCache&) = delete;
   ~ClientPaintCache();
 
+  ClientPaintCache& operator=(const ClientPaintCache&) = delete;
+
   bool Get(PaintCacheDataType type, PaintCacheId id);
   void Put(PaintCacheDataType type, PaintCacheId id, size_t size);
 
@@ -89,8 +92,6 @@
   // send them to the service-side cache. This is necessary to ensure we
   // maintain an accurate mirror of the service-side state.
   base::StackVector<CacheKey, 1> pending_entries_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientPaintCache);
 };
 
 class CC_PAINT_EXPORT ServicePaintCache {
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h
index 342e20e4..0f0c694e 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -6,7 +6,6 @@
 #define CC_PAINT_PAINT_CANVAS_H_
 
 #include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "cc/paint/paint_export.h"
@@ -42,8 +41,11 @@
 // from SkCanvas to PaintCanvas or from SkPicture back into PaintRecord.
 class CC_PAINT_EXPORT PaintCanvas {
  public:
-  PaintCanvas() {}
-  virtual ~PaintCanvas() {}
+  PaintCanvas() = default;
+  PaintCanvas(const PaintCanvas&) = delete;
+  virtual ~PaintCanvas() = default;
+
+  PaintCanvas& operator=(const PaintCanvas&) = delete;
 
   // TODO(enne): this only appears to mostly be used to determine if this is
   // recording or not, so could be simplified or removed.
@@ -193,8 +195,6 @@
 
  private:
   printing::MetafileSkia* metafile_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintCanvas);
 };
 
 class CC_PAINT_EXPORT PaintCanvasAutoRestore {
diff --git a/cc/paint/paint_filter.h b/cc/paint/paint_filter.h
index 7710d501..bdf724a 100644
--- a/cc/paint/paint_filter.h
+++ b/cc/paint/paint_filter.h
@@ -72,8 +72,11 @@
   using MapDirection = SkImageFilter::MapDirection;
   using CropRect = SkImageFilter::CropRect;
 
+  PaintFilter(const PaintFilter&) = delete;
   ~PaintFilter() override;
 
+  PaintFilter& operator=(const PaintFilter&) = delete;
+
   static std::string TypeToString(Type type);
 
   // Returns the size required to serialize the |filter|. Note that |filter| can
@@ -156,8 +159,6 @@
   const bool has_discardable_images_;
 
   ImageAnalysisState image_analysis_state_ = ImageAnalysisState::kNoAnalysis;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintFilter);
 };
 
 class CC_PAINT_EXPORT ColorFilterPaintFilter final : public PaintFilter {
diff --git a/cc/paint/paint_image_generator.h b/cc/paint/paint_image_generator.h
index d0ce1c7..db33427 100644
--- a/cc/paint/paint_image_generator.h
+++ b/cc/paint/paint_image_generator.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/paint/frame_metadata.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_image.h"
@@ -25,8 +24,11 @@
 // be called from any thread.
 class CC_PAINT_EXPORT PaintImageGenerator : public SkRefCnt {
  public:
+  PaintImageGenerator(const PaintImageGenerator&) = delete;
   ~PaintImageGenerator() override;
 
+  PaintImageGenerator& operator=(const PaintImageGenerator&) = delete;
+
   // Returns a reference to the encoded content of this image.
   virtual sk_sp<SkData> GetEncodedData() const = 0;
 
@@ -87,8 +89,6 @@
   const SkImageInfo info_;
   const PaintImage::ContentId generator_content_id_;
   const std::vector<FrameMetadata> frames_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintImageGenerator);
 };
 
 }  // namespace cc
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 8ab8147..99dcf00 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -2245,7 +2245,7 @@
   Reset();
 }
 
-void PaintOpBuffer::operator=(PaintOpBuffer&& other) {
+PaintOpBuffer& PaintOpBuffer::operator=(PaintOpBuffer&& other) {
   data_ = std::move(other.data_);
   used_ = other.used_;
   reserved_ = other.reserved_;
@@ -2260,6 +2260,7 @@
   other.used_ = 0;
   other.op_count_ = 0;
   other.reserved_ = 0;
+  return *this;
 }
 
 void PaintOpBuffer::Reset() {
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index e7e36a5..54725c8 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -920,10 +920,12 @@
   }
 
   PaintOpBuffer();
+  PaintOpBuffer(const PaintOpBuffer&) = delete;
   PaintOpBuffer(PaintOpBuffer&& other);
   ~PaintOpBuffer() override;
 
-  void operator=(PaintOpBuffer&& other);
+  PaintOpBuffer& operator=(const PaintOpBuffer&) = delete;
+  PaintOpBuffer& operator=(PaintOpBuffer&& other);
 
   void Reset();
 
@@ -1230,8 +1232,6 @@
 
   bool has_non_aa_paint_ : 1;
   bool has_discardable_images_ : 1;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
 };
 
 }  // namespace cc
diff --git a/cc/paint/paint_recorder.h b/cc/paint/paint_recorder.h
index c8f1c8a..58b26fa3 100644
--- a/cc/paint/paint_recorder.h
+++ b/cc/paint/paint_recorder.h
@@ -6,7 +6,6 @@
 #define CC_PAINT_PAINT_RECORDER_H_
 
 #include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/optional.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/record_paint_canvas.h"
@@ -18,8 +17,11 @@
 class CC_PAINT_EXPORT PaintRecorder {
  public:
   PaintRecorder();
+  PaintRecorder(const PaintRecorder&) = delete;
   ~PaintRecorder();
 
+  PaintRecorder& operator=(const PaintRecorder&) = delete;
+
   PaintCanvas* beginRecording(const SkRect& bounds);
 
   // TODO(enne): should make everything go through the non-rect version.
@@ -38,7 +40,6 @@
  private:
   scoped_refptr<DisplayItemList> display_item_list_;
   base::Optional<RecordPaintCanvas> canvas_;
-  DISALLOW_COPY_AND_ASSIGN(PaintRecorder);
 };
 
 }  // namespace cc
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h
index 17cbd1f..0f715bc 100644
--- a/cc/paint/paint_shader.h
+++ b/cc/paint/paint_shader.h
@@ -112,8 +112,11 @@
 
   static size_t GetSerializedSize(const PaintShader* shader);
 
+  PaintShader(const PaintShader&) = delete;
   ~PaintShader() override;
 
+  PaintShader& operator=(const PaintShader&) = delete;
+
   void set_has_animated_images(bool has_animated_images) {
     image_analysis_state_ = has_animated_images
                                 ? ImageAnalysisState::kAnimatedImages
@@ -244,8 +247,6 @@
   sk_sp<SkShader> cached_shader_;
 
   ImageAnalysisState image_analysis_state_ = ImageAnalysisState::kNoAnalysis;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintShader);
 };
 
 }  // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
index b0a75cc7..c32547f2 100644
--- a/cc/paint/record_paint_canvas.h
+++ b/cc/paint/record_paint_canvas.h
@@ -9,7 +9,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/optional.h"
 #include "build/build_config.h"
 #include "cc/paint/paint_canvas.h"
@@ -25,8 +24,11 @@
 class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas {
  public:
   RecordPaintCanvas(DisplayItemList* list, const SkRect& bounds);
+  RecordPaintCanvas(const RecordPaintCanvas&) = delete;
   ~RecordPaintCanvas() override;
 
+  RecordPaintCanvas& operator=(const RecordPaintCanvas&) = delete;
+
   SkImageInfo imageInfo() const override;
 
   void flush() override;
@@ -130,8 +132,6 @@
   // lazy initialize the canvas can still be const.
   mutable base::Optional<SkNoDrawCanvas> canvas_;
   SkRect recording_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(RecordPaintCanvas);
 };
 
 }  // namespace cc
diff --git a/cc/paint/render_surface_filters.h b/cc/paint/render_surface_filters.h
index 903ae21..1ca44be5 100644
--- a/cc/paint/render_surface_filters.h
+++ b/cc/paint/render_surface_filters.h
@@ -5,7 +5,6 @@
 #ifndef CC_PAINT_RENDER_SURFACE_FILTERS_H_
 #define CC_PAINT_RENDER_SURFACE_FILTERS_H_
 
-#include "base/macros.h"
 #include "cc/paint/paint_export.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/gfx/geometry/vector2d_f.h"
@@ -20,13 +19,12 @@
 
 class CC_PAINT_EXPORT RenderSurfaceFilters {
  public:
+  RenderSurfaceFilters() = delete;
+
   static sk_sp<PaintFilter> BuildImageFilter(
       const FilterOperations& filters,
       const gfx::SizeF& size,
       const gfx::Vector2dF& offset = gfx::Vector2dF(0, 0));
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(RenderSurfaceFilters);
 };
 
 }  // namespace cc
diff --git a/cc/paint/scoped_raster_flags.h b/cc/paint/scoped_raster_flags.h
index 91a6b871..53b4b38 100644
--- a/cc/paint/scoped_raster_flags.h
+++ b/cc/paint/scoped_raster_flags.h
@@ -6,7 +6,6 @@
 #define CC_PAINT_SCOPED_RASTER_FLAGS_H_
 
 #include "base/containers/stack_container.h"
-#include "base/macros.h"
 #include "cc/paint/decode_stashing_image_provider.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_flags.h"
@@ -22,8 +21,11 @@
                     ImageProvider* image_provider,
                     const SkMatrix& ctm,
                     uint8_t alpha);
+  ScopedRasterFlags(const ScopedRasterFlags&) = delete;
   ~ScopedRasterFlags();
 
+  ScopedRasterFlags& operator=(const ScopedRasterFlags&) = delete;
+
   // The usage of these flags should not extend beyond the lifetime of this
   // object.
   const PaintFlags* flags() const {
@@ -50,8 +52,6 @@
   base::Optional<PaintFlags> modified_flags_;
   base::Optional<DecodeStashingImageProvider> decode_stashing_image_provider_;
   bool decode_failed_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedRasterFlags);
 };
 
 }  // namespace cc
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index b3f665a..3f32da0 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -9,7 +9,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "build/build_config.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_flags.h"
@@ -44,8 +43,11 @@
                   sk_sp<SkColorSpace> target_color_space,
                   ImageProvider* image_provider = nullptr,
                   ContextFlushes context_flushes = ContextFlushes());
+  SkiaPaintCanvas(const SkiaPaintCanvas&) = delete;
   ~SkiaPaintCanvas() override;
 
+  SkiaPaintCanvas& operator=(const SkiaPaintCanvas&) = delete;
+
   void reset_image_provider() { image_provider_ = nullptr; }
 
   SkImageInfo imageInfo() const override;
@@ -152,8 +154,6 @@
 
   const ContextFlushes context_flushes_;
   int num_of_ops_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(SkiaPaintCanvas);
 };
 
 }  // namespace cc
diff --git a/cc/paint/skia_paint_image_generator.h b/cc/paint/skia_paint_image_generator.h
index 55068c2..a3c2ced 100644
--- a/cc/paint/skia_paint_image_generator.h
+++ b/cc/paint/skia_paint_image_generator.h
@@ -5,7 +5,6 @@
 #ifndef CC_PAINT_SKIA_PAINT_IMAGE_GENERATOR_H_
 #define CC_PAINT_SKIA_PAINT_IMAGE_GENERATOR_H_
 
-#include "base/macros.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_image.h"
 #include "third_party/skia/include/core/SkImageGenerator.h"
@@ -18,8 +17,11 @@
   SkiaPaintImageGenerator(sk_sp<PaintImageGenerator> paint_image_generator,
                           size_t frame_index,
                           PaintImage::GeneratorClientId client_id);
+  SkiaPaintImageGenerator(const SkiaPaintImageGenerator&) = delete;
   ~SkiaPaintImageGenerator() override;
 
+  SkiaPaintImageGenerator& operator=(const SkiaPaintImageGenerator&) = delete;
+
   sk_sp<SkData> onRefEncodedData() override;
   bool onGetPixels(const SkImageInfo&,
                    void* pixels,
@@ -36,8 +38,6 @@
   sk_sp<PaintImageGenerator> paint_image_generator_;
   const size_t frame_index_;
   const PaintImage::GeneratorClientId client_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SkiaPaintImageGenerator);
 };
 
 }  // namespace cc
diff --git a/cc/paint/skottie_wrapper.h b/cc/paint/skottie_wrapper.h
index f4e312e..7690059 100644
--- a/cc/paint/skottie_wrapper.h
+++ b/cc/paint/skottie_wrapper.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
 #include "cc/paint/paint_export.h"
@@ -32,6 +31,9 @@
   explicit SkottieWrapper(
       const scoped_refptr<base::RefCountedMemory>& data_stream);
   explicit SkottieWrapper(std::unique_ptr<SkMemoryStream> stream);
+  SkottieWrapper(const SkottieWrapper&) = delete;
+
+  SkottieWrapper& operator=(const SkottieWrapper&) = delete;
 
   // A thread safe call that will draw an image with bounds |rect| for the
   // frame at normalized time instant |t| onto the |canvas|.
@@ -46,8 +48,6 @@
 
   base::Lock lock_;
   sk_sp<skottie::Animation> animation_;
-
-  DISALLOW_COPY_AND_ASSIGN(SkottieWrapper);
 };
 
 }  // namespace cc
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc
index e2713a24..f94e220c 100644
--- a/cc/raster/bitmap_raster_buffer_provider.cc
+++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -9,7 +9,6 @@
 
 #include <algorithm>
 
-#include "base/macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event.h"
@@ -54,6 +53,8 @@
         resource_has_previous_content_(
             resource_content_id && resource_content_id == previous_content_id) {
   }
+  BitmapRasterBufferImpl(const BitmapRasterBufferImpl&) = delete;
+  BitmapRasterBufferImpl& operator=(const BitmapRasterBufferImpl&) = delete;
 
   // Overridden from RasterBuffer:
   void Playback(const RasterSource* raster_source,
@@ -83,8 +84,6 @@
   const gfx::ColorSpace color_space_;
   void* const pixels_;
   bool resource_has_previous_content_;
-
-  DISALLOW_COPY_AND_ASSIGN(BitmapRasterBufferImpl);
 };
 
 }  // namespace
diff --git a/cc/raster/bitmap_raster_buffer_provider.h b/cc/raster/bitmap_raster_buffer_provider.h
index f9c1b9e..e91ac1a4 100644
--- a/cc/raster/bitmap_raster_buffer_provider.h
+++ b/cc/raster/bitmap_raster_buffer_provider.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include "base/macros.h"
 #include "base/values.h"
 #include "cc/raster/raster_buffer_provider.h"
 
@@ -22,8 +21,12 @@
 
 class CC_EXPORT BitmapRasterBufferProvider : public RasterBufferProvider {
  public:
+  BitmapRasterBufferProvider(const BitmapRasterBufferProvider&) = delete;
   ~BitmapRasterBufferProvider() override;
 
+  BitmapRasterBufferProvider& operator=(const BitmapRasterBufferProvider&) =
+      delete;
+
   explicit BitmapRasterBufferProvider(LayerTreeFrameSink* frame_sink);
 
   // Overridden from RasterBufferProvider:
@@ -50,8 +53,6 @@
       const;
 
   LayerTreeFrameSink* const frame_sink_;
-
-  DISALLOW_COPY_AND_ASSIGN(BitmapRasterBufferProvider);
 };
 
 }  // namespace cc
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index c6677e1..bef3681 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -7,8 +7,8 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <utility>
 
-#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
@@ -45,6 +45,7 @@
  public:
   ScopedSkSurfaceForUnpremultiplyAndDither(
       viz::RasterContextProvider* context_provider,
+      sk_sp<SkColorSpace> color_space,
       const gfx::Rect& playback_rect,
       const gfx::Rect& raster_full_rect,
       const gfx::Size& max_tile_size,
@@ -72,8 +73,9 @@
 
     // Allocate a 32-bit surface for raster. We will copy from that into our
     // actual surface in destruction.
-    SkImageInfo n32Info = SkImageInfo::MakeN32Premul(
-        intermediate_size.width(), intermediate_size.height());
+    SkImageInfo n32Info = SkImageInfo::MakeN32Premul(intermediate_size.width(),
+                                                     intermediate_size.height(),
+                                                     std::move(color_space));
     SkSurfaceProps surface_props =
         viz::ClientResourceProvider::ScopedSkSurface::ComputeSurfaceProps(
             can_use_lcd_text);
@@ -207,16 +209,18 @@
     base::Optional<ScopedSkSurfaceForUnpremultiplyAndDither>
         scoped_dither_surface;
     SkSurface* surface;
+    sk_sp<SkColorSpace> sk_color_space = color_space.ToSkColorSpace();
     if (!unpremultiply_and_dither) {
-      scoped_surface.emplace(context_provider->GrContext(), texture_id,
-                             texture_target, resource_size, resource_format,
-                             playback_settings.use_lcd_text, msaa_sample_count);
+      scoped_surface.emplace(context_provider->GrContext(), sk_color_space,
+                             texture_id, texture_target, resource_size,
+                             resource_format, playback_settings.use_lcd_text,
+                             msaa_sample_count);
       surface = scoped_surface->surface();
     } else {
       scoped_dither_surface.emplace(
-          context_provider, playback_rect, raster_full_rect, max_tile_size,
-          texture_id, resource_size, playback_settings.use_lcd_text,
-          msaa_sample_count);
+          context_provider, sk_color_space, playback_rect, raster_full_rect,
+          max_tile_size, texture_id, resource_size,
+          playback_settings.use_lcd_text, msaa_sample_count);
       surface = scoped_dither_surface->surface();
     }
 
@@ -234,8 +238,8 @@
       canvas->discard();
 
     gfx::Size content_size = raster_source->GetContentSize(transform.scale());
-    raster_source->PlaybackToCanvas(canvas, color_space, content_size,
-                                    raster_full_rect, playback_rect, transform,
+    raster_source->PlaybackToCanvas(canvas, content_size, raster_full_rect,
+                                    playback_rect, transform,
                                     playback_settings);
   }
 
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h
index cf72686..52fb765 100644
--- a/cc/raster/gpu_raster_buffer_provider.h
+++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -8,7 +8,6 @@
 #include <stdint.h>
 #include <random>
 
-#include "base/macros.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "gpu/command_buffer/common/sync_token.h"
 
@@ -37,8 +36,11 @@
                           bool unpremultiply_and_dither_low_bit_depth_tiles,
                           bool enable_oop_rasterization,
                           int raster_metric_frequency = kRasterMetricFrequency);
+  GpuRasterBufferProvider(const GpuRasterBufferProvider&) = delete;
   ~GpuRasterBufferProvider() override;
 
+  GpuRasterBufferProvider& operator=(const GpuRasterBufferProvider&) = delete;
+
   // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const ResourcePool::InUsePoolResource& resource,
@@ -84,8 +86,11 @@
                      const ResourcePool::InUsePoolResource& in_use_resource,
                      GpuRasterBacking* backing,
                      bool resource_has_previous_content);
+    RasterBufferImpl(const RasterBufferImpl&) = delete;
     ~RasterBufferImpl() override;
 
+    RasterBufferImpl& operator=(const RasterBufferImpl&) = delete;
+
     // Overridden from RasterBuffer:
     void Playback(const RasterSource* raster_source,
                   const gfx::Rect& raster_full_rect,
@@ -113,8 +118,6 @@
     // A SyncToken to be returned from the worker thread, and waited on before
     // using the rastered resource.
     gpu::SyncToken after_raster_sync_token_;
-
-    DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
   };
 
   struct PendingRasterQuery {
@@ -163,8 +166,6 @@
   // Accessed with the worker context lock acquired.
   std::mt19937 random_generator_;
   std::uniform_int_distribution<int> uniform_distribution_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuRasterBufferProvider);
 };
 
 }  // namespace cc
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index f16e9083..bbdf3744 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/debug/alias.h"
-#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/process_memory_dump.h"
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h
index c2dec8e7..40aaf1d 100644
--- a/cc/raster/one_copy_raster_buffer_provider.h
+++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include "base/macros.h"
 #include "base/sequenced_task_runner.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/raster/staging_buffer_pool.h"
@@ -39,8 +38,12 @@
       bool use_gpu_memory_buffer_resources,
       int max_staging_buffer_usage_in_bytes,
       viz::ResourceFormat tile_format);
+  OneCopyRasterBufferProvider(const OneCopyRasterBufferProvider&) = delete;
   ~OneCopyRasterBufferProvider() override;
 
+  OneCopyRasterBufferProvider& operator=(const OneCopyRasterBufferProvider&) =
+      delete;
+
   // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const ResourcePool::InUsePoolResource& resource,
@@ -87,8 +90,11 @@
                      const ResourcePool::InUsePoolResource& in_use_resource,
                      OneCopyGpuBacking* backing,
                      uint64_t previous_content_id);
+    RasterBufferImpl(const RasterBufferImpl&) = delete;
     ~RasterBufferImpl() override;
 
+    RasterBufferImpl& operator=(const RasterBufferImpl&) = delete;
+
     // Overridden from RasterBuffer:
     void Playback(const RasterSource* raster_source,
                   const gfx::Rect& raster_full_rect,
@@ -115,8 +121,6 @@
     // A SyncToken to be returned from the worker thread, and waited on before
     // using the rastered resource.
     gpu::SyncToken after_raster_sync_token_;
-
-    DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
   };
 
   void PlaybackToStagingBuffer(
@@ -154,8 +158,6 @@
 
   const viz::ResourceFormat tile_format_;
   StagingBufferPool staging_pool_;
-
-  DISALLOW_COPY_AND_ASSIGN(OneCopyRasterBufferProvider);
 };
 
 }  // namespace cc
diff --git a/cc/raster/paint_worklet_image_provider.h b/cc/raster/paint_worklet_image_provider.h
index fe67887..866a348 100644
--- a/cc/raster/paint_worklet_image_provider.h
+++ b/cc/raster/paint_worklet_image_provider.h
@@ -17,17 +17,18 @@
 class CC_EXPORT PaintWorkletImageProvider {
  public:
   explicit PaintWorkletImageProvider(PaintWorkletImageCache* cache);
+  PaintWorkletImageProvider(const PaintWorkletImageProvider&) = delete;
+  PaintWorkletImageProvider(PaintWorkletImageProvider&& other);
   ~PaintWorkletImageProvider();
 
-  PaintWorkletImageProvider(PaintWorkletImageProvider&& other);
+  PaintWorkletImageProvider& operator=(const PaintWorkletImageProvider&) =
+      delete;
   PaintWorkletImageProvider& operator=(PaintWorkletImageProvider&& other);
 
   ImageProvider::ScopedResult GetPaintRecordResult(PaintWorkletInput* input);
 
  private:
   PaintWorkletImageCache* cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintWorkletImageProvider);
 };
 
 }  // namespace cc
diff --git a/cc/raster/playback_image_provider.h b/cc/raster/playback_image_provider.h
index 5e76746e..864ec25 100644
--- a/cc/raster/playback_image_provider.h
+++ b/cc/raster/playback_image_provider.h
@@ -23,6 +23,8 @@
     Settings(const Settings&) = delete;
     Settings(Settings&&);
     ~Settings();
+
+    Settings& operator=(const Settings&) = delete;
     Settings& operator=(Settings&&);
 
     // The set of image ids to skip during raster.
@@ -36,9 +38,11 @@
   // If no settings are provided, all images are skipped during rasterization.
   PlaybackImageProvider(ImageDecodeCache* cache,
                         base::Optional<Settings>&& settings);
+  PlaybackImageProvider(const PlaybackImageProvider&) = delete;
+  PlaybackImageProvider(PlaybackImageProvider&& other);
   ~PlaybackImageProvider() override;
 
-  PlaybackImageProvider(PlaybackImageProvider&& other);
+  PlaybackImageProvider& operator=(const PlaybackImageProvider&) = delete;
   PlaybackImageProvider& operator=(PlaybackImageProvider&& other);
 
   // ImageProvider implementation.
@@ -48,8 +52,6 @@
  private:
   ImageDecodeCache* cache_;
   base::Optional<Settings> settings_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlaybackImageProvider);
 };
 
 }  // namespace cc
diff --git a/cc/raster/raster_buffer_provider.cc b/cc/raster/raster_buffer_provider.cc
index 0e7d1c71..f5935e2 100644
--- a/cc/raster/raster_buffer_provider.cc
+++ b/cc/raster/raster_buffer_provider.cc
@@ -74,7 +74,8 @@
 
   // Uses kPremul_SkAlphaType since the result is not known to be opaque.
   SkImageInfo info =
-      SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType);
+      SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType,
+                           target_color_space.ToSkColorSpace());
 
   // Use unknown pixel geometry to disable LCD text.
   SkSurfaceProps surface_props(0, kUnknown_SkPixelGeometry);
@@ -100,19 +101,18 @@
       // invalid content, just crash the renderer and try again.
       // See: http://crbug.com/721744.
       CHECK(surface);
-      raster_source->PlaybackToCanvas(surface->getCanvas(), target_color_space,
-                                      content_size, canvas_bitmap_rect,
-                                      canvas_playback_rect, transform,
-                                      playback_settings);
+      raster_source->PlaybackToCanvas(surface->getCanvas(), content_size,
+                                      canvas_bitmap_rect, canvas_playback_rect,
+                                      transform, playback_settings);
       return;
     }
     case viz::RGBA_4444: {
       sk_sp<SkSurface> surface = SkSurface::MakeRaster(info, &surface_props);
       // TODO(reveman): Improve partial raster support by reducing the size of
       // playback rect passed to PlaybackToCanvas. crbug.com/519070
-      raster_source->PlaybackToCanvas(
-          surface->getCanvas(), target_color_space, content_size,
-          canvas_bitmap_rect, canvas_bitmap_rect, transform, playback_settings);
+      raster_source->PlaybackToCanvas(surface->getCanvas(), content_size,
+                                      canvas_bitmap_rect, canvas_bitmap_rect,
+                                      transform, playback_settings);
 
       TRACE_EVENT0("cc",
                    "RasterBufferProvider::PlaybackToMemory::ConvertRGBA4444");
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 6eb36031..b6c14bd 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/macros.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/time/time.h"
 #include "base/timer/lap_timer.h"
@@ -182,6 +181,9 @@
 class PerfImageDecodeTaskImpl : public PerfTileTask {
  public:
   PerfImageDecodeTaskImpl() = default;
+  PerfImageDecodeTaskImpl(const PerfImageDecodeTaskImpl&) = delete;
+
+  PerfImageDecodeTaskImpl& operator=(const PerfImageDecodeTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {}
@@ -191,9 +193,6 @@
 
  protected:
   ~PerfImageDecodeTaskImpl() override = default;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
 };
 
 class PerfRasterBufferProviderHelper {
@@ -214,6 +213,8 @@
         pool_(pool),
         resource_(std::move(in_use_resource)),
         raster_buffer_(std::move(raster_buffer)) {}
+  PerfRasterTaskImpl(const PerfRasterTaskImpl&) = delete;
+  PerfRasterTaskImpl& operator=(const PerfRasterTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {}
@@ -236,8 +237,6 @@
   ResourcePool* const pool_;
   ResourcePool::InUsePoolResource resource_;
   std::unique_ptr<RasterBuffer> raster_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl);
 };
 
 class RasterBufferProviderPerfTestBase {
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index 89332a7c..df22550 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/bind_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -72,6 +71,8 @@
         id_(id),
         raster_buffer_(std::move(raster_buffer)),
         raster_source_(FakeRasterSource::CreateFilled(gfx::Size(1, 1))) {}
+  TestRasterTaskImpl(const TestRasterTaskImpl&) = delete;
+  TestRasterTaskImpl& operator=(const TestRasterTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
@@ -98,8 +99,6 @@
   std::unique_ptr<RasterBuffer> raster_buffer_;
   scoped_refptr<RasterSource> raster_source_;
   GURL url_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
 };
 
 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
@@ -115,6 +114,9 @@
                            std::move(raster_buffer),
                            dependencies),
         lock_(lock) {}
+  BlockingTestRasterTaskImpl(const BlockingTestRasterTaskImpl&) = delete;
+  BlockingTestRasterTaskImpl& operator=(const BlockingTestRasterTaskImpl&) =
+      delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
@@ -127,8 +129,6 @@
 
  private:
   base::Lock* lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
 };
 
 class RasterBufferProviderTest
diff --git a/cc/raster/raster_source.cc b/cc/raster/raster_source.cc
index 8f510fa..8c490e48 100644
--- a/cc/raster/raster_source.cc
+++ b/cc/raster/raster_source.cc
@@ -16,7 +16,6 @@
 #include "cc/paint/skia_paint_canvas.h"
 #include "components/viz/common/traced_value.h"
 #include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
 #include "ui/gfx/geometry/axis_transform2d.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -111,8 +110,7 @@
 }
 
 void RasterSource::PlaybackToCanvas(
-    SkCanvas* input_canvas,
-    const gfx::ColorSpace& target_color_space,
+    SkCanvas* raster_canvas,
     const gfx::Size& content_size,
     const gfx::Rect& canvas_bitmap_rect,
     const gfx::Rect& canvas_playback_rect,
@@ -125,15 +123,6 @@
   // Treat all subnormal values as zero for performance.
   ScopedSubnormalFloatDisabler disabler;
 
-  // TODO(enne): color transform needs to be replicated in gles2_cmd_decoder
-  SkCanvas* raster_canvas = input_canvas;
-  std::unique_ptr<SkCanvas> color_transform_canvas;
-  if (target_color_space.IsValid()) {
-    color_transform_canvas = SkCreateColorSpaceXformCanvas(
-        input_canvas, target_color_space.ToSkColorSpace());
-    raster_canvas = color_transform_canvas.get();
-  }
-
   bool is_partial_raster = canvas_bitmap_rect != canvas_playback_rect;
   if (!requires_clear_) {
     // Clear opaque raster sources.  Opaque rasters sources guarantee that all
diff --git a/cc/raster/raster_source.h b/cc/raster/raster_source.h
index d4d45ff5..43ec5f3 100644
--- a/cc/raster/raster_source.h
+++ b/cc/raster/raster_source.h
@@ -10,7 +10,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/debug/rendering_stats_instrumentation.h"
 #include "cc/layers/recording_source.h"
@@ -41,6 +40,9 @@
     ImageProvider* image_provider = nullptr;
   };
 
+  RasterSource(const RasterSource&) = delete;
+  RasterSource& operator=(const RasterSource&) = delete;
+
   // Helper function to apply a few common operations before passing the canvas
   // to the shorter version. This is useful for rastering into tiles.
   // canvas is expected to be backed by a tile, with a default state.
@@ -51,7 +53,6 @@
   // canvas_playback_rect can be used to replay only part of the recording in,
   // the content space, so only a sub-rect of the tile gets rastered.
   void PlaybackToCanvas(SkCanvas* canvas,
-                        const gfx::ColorSpace& target_color_space,
                         const gfx::Size& content_size,
                         const gfx::Rect& canvas_bitmap_rect,
                         const gfx::Rect& canvas_playback_rect,
@@ -145,8 +146,6 @@
   const gfx::Size size_;
   const int slow_down_raster_scale_factor_for_debug_;
   const float recording_scale_factor_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterSource);
 };
 
 }  // namespace cc
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc
index c694083..21338cf 100644
--- a/cc/raster/raster_source_unittest.cc
+++ b/cc/raster/raster_source_unittest.cc
@@ -30,10 +30,6 @@
 namespace cc {
 namespace {
 
-gfx::ColorSpace ColorSpaceForTesting() {
-  return gfx::ColorSpace();
-}
-
 TEST(RasterSourceTest, AnalyzeIsSolidUnscaled) {
   gfx::Size layer_bounds(400, 400);
 
@@ -346,8 +342,8 @@
       canvas.clear(SK_ColorTRANSPARENT);
 
       raster->PlaybackToCanvas(
-          &canvas, ColorSpaceForTesting(), content_bounds, canvas_rect,
-          canvas_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
+          &canvas, content_bounds, canvas_rect, canvas_rect,
+          gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
           RasterSource::PlaybackSettings());
 
       SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
@@ -398,8 +394,8 @@
   gfx::Rect raster_full_rect(content_bounds);
   gfx::Rect playback_rect(content_bounds);
   raster->PlaybackToCanvas(
-      &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect,
-      playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
+      &canvas, content_bounds, raster_full_rect, playback_rect,
+      gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
       RasterSource::PlaybackSettings());
 
   {
@@ -430,8 +426,8 @@
   // that touches the edge pixels of the recording.
   playback_rect.Inset(1, 2, 0, 1);
   raster->PlaybackToCanvas(
-      &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect,
-      playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
+      &canvas, content_bounds, raster_full_rect, playback_rect,
+      gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
       RasterSource::PlaybackSettings());
 
   SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
@@ -495,8 +491,8 @@
   gfx::Rect raster_full_rect(content_bounds);
   gfx::Rect playback_rect(content_bounds);
   raster->PlaybackToCanvas(
-      &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect,
-      playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
+      &canvas, content_bounds, raster_full_rect, playback_rect,
+      gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
       RasterSource::PlaybackSettings());
 
   {
@@ -535,8 +531,8 @@
   playback_rect =
       gfx::Rect(gfx::ScaleToCeiledSize(partial_bounds, contents_scale));
   raster->PlaybackToCanvas(
-      &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect,
-      playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
+      &canvas, content_bounds, raster_full_rect, playback_rect,
+      gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
       RasterSource::PlaybackSettings());
 
   // Test that the whole playback_rect was cleared and repainted with new alpha.
@@ -576,7 +572,7 @@
   SkCanvas canvas(bitmap);
 
   raster->PlaybackToCanvas(
-      &canvas, ColorSpaceForTesting(), content_bounds, canvas_rect, canvas_rect,
+      &canvas, content_bounds, canvas_rect, canvas_rect,
       gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
       RasterSource::PlaybackSettings());
 
@@ -623,9 +619,8 @@
   EXPECT_CALL(mock_canvas, willRestore()).InSequence(s);
 
   gfx::Size small_size(50, 50);
-  raster_source->PlaybackToCanvas(&mock_canvas, ColorSpaceForTesting(), size,
-                                  gfx::Rect(small_size), gfx::Rect(small_size),
-                                  gfx::AxisTransform2d(),
+  raster_source->PlaybackToCanvas(&mock_canvas, size, gfx::Rect(small_size),
+                                  gfx::Rect(small_size), gfx::AxisTransform2d(),
                                   RasterSource::PlaybackSettings());
 }
 
diff --git a/cc/raster/scoped_gpu_raster.h b/cc/raster/scoped_gpu_raster.h
index 9f4e0c84..0ccd91c 100644
--- a/cc/raster/scoped_gpu_raster.h
+++ b/cc/raster/scoped_gpu_raster.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "cc/cc_export.h"
 
 namespace viz {
@@ -23,15 +22,16 @@
 class CC_EXPORT ScopedGpuRaster {
  public:
   explicit ScopedGpuRaster(viz::ContextProvider* context_provider);
+  ScopedGpuRaster(const ScopedGpuRaster&) = delete;
   ~ScopedGpuRaster();
 
+  ScopedGpuRaster& operator=(const ScopedGpuRaster&) = delete;
+
  private:
   void BeginGpuRaster();
   void EndGpuRaster();
 
   viz::ContextProvider* context_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedGpuRaster);
 };
 
 }  // namespace cc
diff --git a/cc/raster/staging_buffer_pool.h b/cc/raster/staging_buffer_pool.h
index d3331323..4b2953b 100644
--- a/cc/raster/staging_buffer_pool.h
+++ b/cc/raster/staging_buffer_pool.h
@@ -11,7 +11,6 @@
 #include <set>
 
 #include "base/containers/circular_deque.h"
-#include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
@@ -81,12 +80,15 @@
 class CC_EXPORT StagingBufferPool
     : public base::trace_event::MemoryDumpProvider {
  public:
-  ~StagingBufferPool() final;
-
   StagingBufferPool(scoped_refptr<base::SequencedTaskRunner> task_runner,
                     viz::RasterContextProvider* worker_context_provider,
                     bool use_partial_raster,
                     int max_staging_buffer_usage_in_bytes);
+  StagingBufferPool(const StagingBufferPool&) = delete;
+  ~StagingBufferPool() final;
+
+  StagingBufferPool& operator=(const StagingBufferPool&) = delete;
+
   void Shutdown();
 
   // Overridden from base::trace_event::MemoryDumpProvider:
@@ -141,8 +143,6 @@
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
   base::WeakPtrFactory<StagingBufferPool> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(StagingBufferPool);
 };
 
 }  // namespace cc
diff --git a/cc/raster/task.h b/cc/raster/task.h
index d67cb7a..5369543 100644
--- a/cc/raster/task.h
+++ b/cc/raster/task.h
@@ -112,18 +112,17 @@
          uint16_t category,
          uint16_t priority,
          uint32_t dependencies);
+    Node(const Node&) = delete;
     Node(Node&& other);
     ~Node();
 
+    Node& operator=(const Node&) = delete;
     Node& operator=(Node&& other) = default;
 
     scoped_refptr<Task> task;
     uint16_t category;
     uint16_t priority;
     uint32_t dependencies;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Node);
   };
 
   struct Edge {
@@ -137,17 +136,18 @@
   };
 
   TaskGraph();
+  TaskGraph(const TaskGraph&) = delete;
   TaskGraph(TaskGraph&& other);
   ~TaskGraph();
 
+  TaskGraph& operator=(const TaskGraph&) = delete;
+  TaskGraph& operator=(TaskGraph&&) = default;
+
   void Swap(TaskGraph* other);
   void Reset();
 
   Node::Vector nodes;
   Edge::Vector edges;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TaskGraph);
 };
 
 }  // namespace cc
diff --git a/cc/raster/task_graph_runner_perftest.cc b/cc/raster/task_graph_runner_perftest.cc
index 36ee90fa..d7f35a0 100644
--- a/cc/raster/task_graph_runner_perftest.cc
+++ b/cc/raster/task_graph_runner_perftest.cc
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "base/timer/lap_timer.h"
@@ -29,6 +28,8 @@
   typedef std::vector<scoped_refptr<PerfTaskImpl>> Vector;
 
   PerfTaskImpl() = default;
+  PerfTaskImpl(const PerfTaskImpl&) = delete;
+  PerfTaskImpl& operator=(const PerfTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {}
@@ -37,8 +38,6 @@
 
  private:
   ~PerfTaskImpl() override = default;
-
-  DISALLOW_COPY_AND_ASSIGN(PerfTaskImpl);
 };
 
 class TaskGraphRunnerPerfTest : public testing::Test {
diff --git a/cc/raster/task_graph_work_queue.h b/cc/raster/task_graph_work_queue.h
index b1bbce8..3b739f72 100644
--- a/cc/raster/task_graph_work_queue.h
+++ b/cc/raster/task_graph_work_queue.h
@@ -35,18 +35,17 @@
                     TaskNamespace* task_namespace,
                     uint16_t category,
                     uint16_t priority);
+    PrioritizedTask(const PrioritizedTask&) = delete;
     PrioritizedTask(PrioritizedTask&& other);
     ~PrioritizedTask();
 
+    PrioritizedTask& operator=(const PrioritizedTask&) = delete;
     PrioritizedTask& operator=(PrioritizedTask&& other) = default;
 
     scoped_refptr<Task> task;
     TaskNamespace* task_namespace;
     uint16_t category;
     uint16_t priority;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(PrioritizedTask);
   };
 
   using CategorizedTask = std::pair<uint16_t, scoped_refptr<Task>>;
@@ -56,9 +55,13 @@
     typedef std::vector<TaskNamespace*> Vector;
 
     TaskNamespace();
+    TaskNamespace(const TaskNamespace&) = delete;
     TaskNamespace(TaskNamespace&& other);
     ~TaskNamespace();
 
+    TaskNamespace& operator=(const TaskNamespace&) = delete;
+    TaskNamespace& operator=(TaskNamespace&&) = default;
+
     // Current task graph.
     TaskGraph graph;
 
@@ -71,14 +74,14 @@
 
     // This set contains all currently running tasks.
     std::vector<CategorizedTask> running_tasks;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(TaskNamespace);
   };
 
   TaskGraphWorkQueue();
+  TaskGraphWorkQueue(const TaskGraphWorkQueue&) = delete;
   virtual ~TaskGraphWorkQueue();
 
+  TaskGraphWorkQueue& operator=(const TaskGraphWorkQueue&) = delete;
+
   // Generates a NamespaceToken which is guaranteed to be unique within this
   // TaskGraphWorkQueue.
   NamespaceToken GenerateNamespaceToken();
@@ -192,8 +195,6 @@
 
   // Provides a unique id to each NamespaceToken.
   int next_namespace_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaskGraphWorkQueue);
 };
 
 }  // namespace cc
diff --git a/cc/raster/task_graph_work_queue_unittest.cc b/cc/raster/task_graph_work_queue_unittest.cc
index 93455db..ac78a6d 100644
--- a/cc/raster/task_graph_work_queue_unittest.cc
+++ b/cc/raster/task_graph_work_queue_unittest.cc
@@ -13,13 +13,15 @@
 class FakeTaskImpl : public Task {
  public:
   FakeTaskImpl() = default;
+  FakeTaskImpl(const FakeTaskImpl&) = delete;
+
+  FakeTaskImpl& operator=(const FakeTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {}
 
  private:
   ~FakeTaskImpl() override = default;
-  DISALLOW_COPY_AND_ASSIGN(FakeTaskImpl);
 };
 
 TEST(TaskGraphWorkQueueTest, TestChangingDependency) {
diff --git a/cc/raster/zero_copy_raster_buffer_provider.cc b/cc/raster/zero_copy_raster_buffer_provider.cc
index 8e5eb1c..6f491eb7 100644
--- a/cc/raster/zero_copy_raster_buffer_provider.cc
+++ b/cc/raster/zero_copy_raster_buffer_provider.cc
@@ -8,7 +8,6 @@
 
 #include <algorithm>
 
-#include "base/macros.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
@@ -75,6 +74,7 @@
         resource_format_(in_use_resource.format()),
         resource_color_space_(in_use_resource.color_space()),
         gpu_memory_buffer_(std::move(backing_->gpu_memory_buffer)) {}
+  ZeroCopyRasterBufferImpl(const ZeroCopyRasterBufferImpl&) = delete;
 
   ~ZeroCopyRasterBufferImpl() override {
     // If GpuMemoryBuffer allocation failed (https://crbug.com/554541), then
@@ -107,6 +107,8 @@
     backing_->gpu_memory_buffer = std::move(gpu_memory_buffer_);
   }
 
+  ZeroCopyRasterBufferImpl& operator=(const ZeroCopyRasterBufferImpl&) = delete;
+
   // Overridden from RasterBuffer:
   void Playback(const RasterSource* raster_source,
                 const gfx::Rect& raster_full_rect,
@@ -154,8 +156,6 @@
   viz::ResourceFormat resource_format_;
   gfx::ColorSpace resource_color_space_;
   std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterBufferImpl);
 };
 
 }  // namespace
diff --git a/cc/raster/zero_copy_raster_buffer_provider.h b/cc/raster/zero_copy_raster_buffer_provider.h
index 680d6b0..6bb0e33 100644
--- a/cc/raster/zero_copy_raster_buffer_provider.h
+++ b/cc/raster/zero_copy_raster_buffer_provider.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "cc/raster/raster_buffer_provider.h"
@@ -30,8 +29,12 @@
       gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
       viz::ContextProvider* compositor_context_provider,
       viz::ResourceFormat tile_format);
+  ZeroCopyRasterBufferProvider(const ZeroCopyRasterBufferProvider&) = delete;
   ~ZeroCopyRasterBufferProvider() override;
 
+  ZeroCopyRasterBufferProvider& operator=(const ZeroCopyRasterBufferProvider&) =
+      delete;
+
   // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const ResourcePool::InUsePoolResource& resource,
@@ -58,8 +61,6 @@
   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
   viz::ContextProvider* compositor_context_provider_;
   viz::ResourceFormat tile_format_;
-
-  DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterBufferProvider);
 };
 
 }  // namespace cc
diff --git a/cc/resources/memory_history.h b/cc/resources/memory_history.h
index 14a2fbb..f5a7e9c8 100644
--- a/cc/resources/memory_history.h
+++ b/cc/resources/memory_history.h
@@ -11,7 +11,6 @@
 #include <memory>
 
 #include "base/containers/ring_buffer.h"
-#include "base/macros.h"
 #include "base/time/time.h"
 
 namespace cc {
@@ -21,6 +20,9 @@
  public:
   static std::unique_ptr<MemoryHistory> Create();
 
+  MemoryHistory(const MemoryHistory&) = delete;
+  MemoryHistory& operator=(const MemoryHistory&) = delete;
+
   size_t HistorySize() const { return ring_buffer_.BufferSize(); }
 
   struct Entry {
@@ -44,8 +46,6 @@
   MemoryHistory();
 
   RingBufferType ring_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryHistory);
 };
 
 }  // namespace cc
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h
index cd72eb84..b7f2f8d 100644
--- a/cc/resources/resource_pool.h
+++ b/cc/resources/resource_pool.h
@@ -12,7 +12,6 @@
 #include <memory>
 
 #include "base/containers/circular_deque.h"
-#include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
@@ -199,8 +198,11 @@
                const base::TimeDelta& expiration_delay,
                bool disallow_non_exact_reuse);
 
+  ResourcePool(const ResourcePool&) = delete;
   ~ResourcePool() override;
 
+  ResourcePool& operator=(const ResourcePool&) = delete;
+
   // Tries to reuse a resource. If none are available, makes a new one.
   InUsePoolResource AcquireResource(const gfx::Size& size,
                                     viz::ResourceFormat format,
@@ -407,8 +409,6 @@
   const base::TickClock* clock_;
 
   base::WeakPtrFactory<ResourcePool> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourcePool);
 };
 
 }  // namespace cc
diff --git a/cc/resources/scoped_ui_resource.h b/cc/resources/scoped_ui_resource.h
index 8b11f7e..e12dabd 100644
--- a/cc/resources/scoped_ui_resource.h
+++ b/cc/resources/scoped_ui_resource.h
@@ -5,7 +5,6 @@
 #ifndef CC_RESOURCES_SCOPED_UI_RESOURCE_H_
 #define CC_RESOURCES_SCOPED_UI_RESOURCE_H_
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/cc_export.h"
 #include "cc/resources/ui_resource_bitmap.h"
@@ -26,8 +25,11 @@
   static std::unique_ptr<ScopedUIResource> Create(
       UIResourceManager* ui_resource_manager,
       const UIResourceBitmap& bitmap);
+  ScopedUIResource(const ScopedUIResource&) = delete;
   ~ScopedUIResource() override;
 
+  ScopedUIResource& operator=(const ScopedUIResource&) = delete;
+
   // UIResourceClient implementation.
   UIResourceBitmap GetBitmap(UIResourceId uid, bool resource_lost) override;
   UIResourceId id() { return id_; }
@@ -42,9 +44,6 @@
   UIResourceBitmap bitmap_;
   UIResourceManager* ui_resource_manager_;
   UIResourceId id_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedUIResource);
 };
 
 }  // namespace cc
diff --git a/cc/resources/shared_bitmap_id_registrar.h b/cc/resources/shared_bitmap_id_registrar.h
index b3533def..6abb30e 100644
--- a/cc/resources/shared_bitmap_id_registrar.h
+++ b/cc/resources/shared_bitmap_id_registrar.h
@@ -49,9 +49,12 @@
 class CC_EXPORT SharedBitmapIdRegistration {
  public:
   SharedBitmapIdRegistration();
+  SharedBitmapIdRegistration(const SharedBitmapIdRegistration&) = delete;
+  SharedBitmapIdRegistration(SharedBitmapIdRegistration&&);
   ~SharedBitmapIdRegistration();
 
-  SharedBitmapIdRegistration(SharedBitmapIdRegistration&&);
+  SharedBitmapIdRegistration& operator=(const SharedBitmapIdRegistration&) =
+      delete;
   SharedBitmapIdRegistration& operator=(SharedBitmapIdRegistration&&);
 
  private:
@@ -63,8 +66,6 @@
 
   base::WeakPtr<TextureLayer> layer_ptr_;
   viz::SharedBitmapId id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedBitmapIdRegistration);
 };
 
 }  // namespace cc
diff --git a/cc/resources/ui_resource_manager.h b/cc/resources/ui_resource_manager.h
index 7f29ba61f..e3e51204 100644
--- a/cc/resources/ui_resource_manager.h
+++ b/cc/resources/ui_resource_manager.h
@@ -8,7 +8,6 @@
 #include <unordered_map>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/resources/ui_resource_request.h"
 
@@ -18,8 +17,11 @@
 class CC_EXPORT UIResourceManager {
  public:
   UIResourceManager();
+  UIResourceManager(const UIResourceManager&) = delete;
   virtual ~UIResourceManager();
 
+  UIResourceManager& operator=(const UIResourceManager&) = delete;
+
   // CreateUIResource creates a resource given a bitmap.  The bitmap is
   // generated via an interface function, which is called when initializing the
   // resource and when the resource has been lost (due to lost context).  The
@@ -65,8 +67,6 @@
   // DeleteUIResource).
   std::unordered_map<SkPixelRef*, std::unique_ptr<ScopedUIResource>>
       owned_shared_resources_;
-
-  DISALLOW_COPY_AND_ASSIGN(UIResourceManager);
 };
 
 }  // namespace cc
diff --git a/cc/scheduler/compositor_timing_history.h b/cc/scheduler/compositor_timing_history.h
index 842583f1..f9559bd 100644
--- a/cc/scheduler/compositor_timing_history.h
+++ b/cc/scheduler/compositor_timing_history.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/base/rolling_time_delta_history.h"
 #include "cc/cc_export.h"
 #include "cc/tiles/tile_priority.h"
@@ -36,8 +35,11 @@
       bool using_synchronous_renderer_compositor,
       UMACategory uma_category,
       RenderingStatsInstrumentation* rendering_stats_instrumentation);
+  CompositorTimingHistory(const CompositorTimingHistory&) = delete;
   virtual ~CompositorTimingHistory();
 
+  CompositorTimingHistory& operator=(const CompositorTimingHistory&) = delete;
+
   void AsValueInto(base::trace_event::TracedValue* state) const;
 
   // The main thread responsiveness depends heavily on whether or not the
@@ -166,9 +168,6 @@
   bool previous_frame_had_raf_ = false;
 
   TreePriority tree_priority_ = SAME_PRIORITY_FOR_BOTH_TREES;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CompositorTimingHistory);
 };
 
 }  // namespace cc
diff --git a/cc/scheduler/compositor_timing_history_unittest.cc b/cc/scheduler/compositor_timing_history_unittest.cc
index a5e8387..c7fd357 100644
--- a/cc/scheduler/compositor_timing_history_unittest.cc
+++ b/cc/scheduler/compositor_timing_history_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "cc/scheduler/compositor_timing_history.h"
 
-#include "base/macros.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "cc/debug/rendering_stats_instrumentation.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -20,14 +19,14 @@
                               RenderingStatsInstrumentation* rendering_stats)
       : CompositorTimingHistory(false, RENDERER_UMA, rendering_stats),
         test_(test) {}
+  TestCompositorTimingHistory(const TestCompositorTimingHistory&) = delete;
+  TestCompositorTimingHistory& operator=(const TestCompositorTimingHistory&) =
+      delete;
 
  protected:
   base::TimeTicks Now() const override;
 
   CompositorTimingHistoryTest* test_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestCompositorTimingHistory);
 };
 
 class CompositorTimingHistoryTest : public testing::Test {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 292a0f5..a84943e 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/cancelable_callback.h"
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/cc_export.h"
 #include "cc/scheduler/begin_frame_tracker.h"
@@ -78,8 +77,11 @@
             int layer_tree_host_id,
             base::SingleThreadTaskRunner* task_runner,
             std::unique_ptr<CompositorTimingHistory> compositor_timing_history);
+  Scheduler(const Scheduler&) = delete;
   ~Scheduler() override;
 
+  Scheduler& operator=(const Scheduler&) = delete;
+
   // This is needed so that the scheduler doesn't perform spurious actions while
   // the compositor is being torn down.
   void Stop();
@@ -322,8 +324,6 @@
   bool IsInsideAction(SchedulerStateMachine::Action action) {
     return inside_action_ == action;
   }
-
-  DISALLOW_COPY_AND_ASSIGN(Scheduler);
 };
 
 }  // namespace cc
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index f683e52..76f3c18 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -10,7 +10,6 @@
 #include <memory>
 #include <string>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/scheduler/commit_earlyout_reason.h"
 #include "cc/scheduler/draw_result.h"
@@ -48,8 +47,11 @@
  public:
   // settings must be valid for the lifetime of this class.
   explicit SchedulerStateMachine(const SchedulerSettings& settings);
+  SchedulerStateMachine(const SchedulerStateMachine&) = delete;
   ~SchedulerStateMachine();
 
+  SchedulerStateMachine& operator=(const SchedulerStateMachine&) = delete;
+
   enum class LayerTreeFrameSinkState {
     NONE,
     ACTIVE,
@@ -457,9 +459,6 @@
   // If set to true, the pending tree must be drawn at least once after
   // activation before a new tree can be activated.
   bool pending_tree_needs_first_draw_on_activation_ = false;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
 };
 
 }  // namespace cc
diff --git a/cc/test/cc_test_suite.h b/cc/test/cc_test_suite.h
index 4e0a114..eef4c273 100644
--- a/cc/test/cc_test_suite.h
+++ b/cc/test/cc_test_suite.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/test/test_discardable_memory_allocator.h"
 #include "base/test/test_suite.h"
 
@@ -20,8 +19,11 @@
 class CCTestSuite : public base::TestSuite {
  public:
   CCTestSuite(int argc, char** argv);
+  CCTestSuite(const CCTestSuite&) = delete;
   ~CCTestSuite() override;
 
+  CCTestSuite& operator=(const CCTestSuite&) = delete;
+
  protected:
   // Overridden from base::TestSuite:
   void Initialize() override;
@@ -31,7 +33,6 @@
   std::unique_ptr<base::MessageLoop> message_loop_;
 
   base::TestDiscardableMemoryAllocator discardable_memory_allocator_;
-  DISALLOW_COPY_AND_ASSIGN(CCTestSuite);
 };
 
 }  // namespace cc
diff --git a/cc/test/fake_paint_image_generator.h b/cc/test/fake_paint_image_generator.h
index e34ab446..8a18535 100644
--- a/cc/test/fake_paint_image_generator.h
+++ b/cc/test/fake_paint_image_generator.h
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/containers/flat_map.h"
-#include "base/macros.h"  // For DISALLOW_COPY_AND_ASSIGN
 #include "cc/paint/paint_image_generator.h"
 
 namespace cc {
@@ -28,8 +27,11 @@
       std::vector<FrameMetadata> frames = {FrameMetadata()},
       bool allocate_discardable_memory = true,
       std::vector<SkISize> supported_sizes = {});
+  FakePaintImageGenerator(const FakePaintImageGenerator&) = delete;
   ~FakePaintImageGenerator() override;
 
+  FakePaintImageGenerator& operator=(const FakePaintImageGenerator&) = delete;
+
   // PaintImageGenerator implementation.
   sk_sp<SkData> GetEncodedData() const override;
   bool GetPixels(const SkImageInfo& info,
@@ -70,8 +72,6 @@
   // planes and after Chrome implements it, we should no longer expect RGB
   // fallback.
   bool expect_fallback_to_rgb_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(FakePaintImageGenerator);
 };
 
 }  // namespace cc
diff --git a/cc/test/fake_scrollbar.h b/cc/test/fake_scrollbar.h
index 56ed6de..e4d7e9c0 100644
--- a/cc/test/fake_scrollbar.h
+++ b/cc/test/fake_scrollbar.h
@@ -6,7 +6,6 @@
 #define CC_TEST_FAKE_SCROLLBAR_H_
 
 #include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "cc/input/scrollbar.h"
 #include "third_party/skia/include/core/SkColor.h"
 
@@ -21,8 +20,11 @@
                 ScrollbarOrientation orientation,
                 bool is_left_side_vertical_scrollbar,
                 bool is_overlay);
+  FakeScrollbar(const FakeScrollbar&) = delete;
   ~FakeScrollbar() override;
 
+  FakeScrollbar& operator=(const FakeScrollbar&) = delete;
+
   // Scrollbar implementation.
   ScrollbarOrientation Orientation() const override;
   bool IsLeftSideVerticalScrollbar() const override;
@@ -75,8 +77,6 @@
   gfx::Point location_;
   gfx::Rect track_rect_;
   SkColor fill_color_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeScrollbar);
 };
 
 }  // namespace cc
diff --git a/cc/test/mock_layer_client.h b/cc/test/mock_layer_client.h
index e5ab750d..0850d24a 100644
--- a/cc/test/mock_layer_client.h
+++ b/cc/test/mock_layer_client.h
@@ -5,7 +5,6 @@
 #ifndef CC_TEST_MOCK_LAYER_CLIENT_H_
 #define CC_TEST_MOCK_LAYER_CLIENT_H_
 
-#include "base/macros.h"
 #include "base/trace_event/trace_event_impl.h"
 #include "base/trace_event/traced_value.h"
 #include "cc/layers/layer_client.h"
@@ -16,14 +15,14 @@
 class MockLayerClient : public LayerClient {
  public:
   MockLayerClient();
+  MockLayerClient(const MockLayerClient&) = delete;
   ~MockLayerClient() override;
 
+  MockLayerClient& operator=(const MockLayerClient&) = delete;
+
   MOCK_METHOD1(TakeDebugInfo,
                std::unique_ptr<base::trace_event::TracedValue>(Layer*));
   MOCK_METHOD1(didChangeScrollbarsHiddenIfOverlay, void(bool));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockLayerClient);
 };
 
 }  // namespace cc
diff --git a/cc/test/mock_occlusion_tracker.h b/cc/test/mock_occlusion_tracker.h
index 47f1f0e..18512bb 100644
--- a/cc/test/mock_occlusion_tracker.h
+++ b/cc/test/mock_occlusion_tracker.h
@@ -5,7 +5,6 @@
 #ifndef CC_TEST_MOCK_OCCLUSION_TRACKER_H_
 #define CC_TEST_MOCK_OCCLUSION_TRACKER_H_
 
-#include "base/macros.h"
 #include "cc/trees/occlusion_tracker.h"
 
 namespace cc {
@@ -28,6 +27,9 @@
     OcclusionTracker::stack_.push_back(stack_obj);
     OcclusionTracker::stack_.push_back(stack_obj);
   }
+  MockOcclusionTracker(const MockOcclusionTracker&) = delete;
+
+  MockOcclusionTracker& operator=(const MockOcclusionTracker&) = delete;
 
   void set_occluded_target_rect(const gfx::Rect& occluded) {
     OcclusionTracker::stack_.back().occlusion_from_inside_target = occluded;
@@ -38,9 +40,6 @@
     OcclusionTracker::stack_[OcclusionTracker::stack_.size() - 2]
         .occlusion_from_inside_target = occluded;
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockOcclusionTracker);
 };
 
 }  // namespace cc
diff --git a/cc/test/push_properties_counting_layer.h b/cc/test/push_properties_counting_layer.h
index 97e71898..d1a9cc4 100644
--- a/cc/test/push_properties_counting_layer.h
+++ b/cc/test/push_properties_counting_layer.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/layers/layer.h"
 
@@ -20,6 +19,10 @@
  public:
   static scoped_refptr<PushPropertiesCountingLayer> Create();
 
+  PushPropertiesCountingLayer(const PushPropertiesCountingLayer&) = delete;
+  PushPropertiesCountingLayer& operator=(const PushPropertiesCountingLayer&) =
+      delete;
+
   // Layer implementation.
   void PushPropertiesTo(LayerImpl* layer) override;
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
@@ -37,8 +40,6 @@
   void AddPushPropertiesCount();
 
   size_t push_properties_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(PushPropertiesCountingLayer);
 };
 
 }  // namespace cc
diff --git a/cc/test/push_properties_counting_layer_impl.h b/cc/test/push_properties_counting_layer_impl.h
index cd79397..2a94002c 100644
--- a/cc/test/push_properties_counting_layer_impl.h
+++ b/cc/test/push_properties_counting_layer_impl.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/layers/layer_impl.h"
 
 namespace cc {
@@ -19,8 +18,13 @@
   static std::unique_ptr<PushPropertiesCountingLayerImpl> Create(
       LayerTreeImpl* tree_impl,
       int id);
+  PushPropertiesCountingLayerImpl(const PushPropertiesCountingLayerImpl&) =
+      delete;
   ~PushPropertiesCountingLayerImpl() override;
 
+  PushPropertiesCountingLayerImpl& operator=(
+      const PushPropertiesCountingLayerImpl&) = delete;
+
   // LayerImpl implementation.
   void PushPropertiesTo(LayerImpl* layer) override;
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
@@ -32,8 +36,6 @@
   PushPropertiesCountingLayerImpl(LayerTreeImpl* tree_impl, int id);
 
   size_t push_properties_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(PushPropertiesCountingLayerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index b3a07b0..b43730d 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -73,8 +73,8 @@
                                  const gfx::Rect& rect,
                                  SkColor color) {
   viz::SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, false, 1,
-                       SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect, false,
+                       false, 1, SkBlendMode::kSrcOver, 0);
   auto* quad = pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
   quad->SetNew(shared_state, rect, rect, color, false);
   return quad;
@@ -84,8 +84,8 @@
                                         const gfx::Rect& rect,
                                         SkColor color) {
   viz::SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect, rect, rect, true, false, 1,
-                       SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect, true,
+                       false, 1, SkBlendMode::kSrcOver, 0);
   auto* quad = pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
   quad->SetNew(shared_state, rect, rect, color, false);
   return quad;
@@ -96,7 +96,8 @@
                                             SkColor color,
                                             const gfx::Transform& transform) {
   viz::SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(transform, rect, rect, rect, false, false, 1,
+  shared_state->SetAll(transform, rect, rect, gfx::RRectF(), rect, false, false,
+                       1,
 
                        SkBlendMode::kSrcOver, 0);
   auto* quad = pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
@@ -109,8 +110,9 @@
   gfx::Rect output_rect = contributing_pass->output_rect;
   viz::SharedQuadState* shared_state =
       to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), output_rect, output_rect, output_rect,
-                       false, false, 1, SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), output_rect, output_rect,
+                       gfx::RRectF(), output_rect, false, false, 1,
+                       SkBlendMode::kSrcOver, 0);
   auto* quad = to_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>();
   quad->SetNew(shared_state, output_rect, output_rect, contributing_pass->id, 0,
                gfx::RectF(), gfx::Size(), gfx::Vector2dF(), gfx::PointF(),
@@ -125,8 +127,8 @@
   gfx::Rect output_rect = contributing_pass->output_rect;
   viz::SharedQuadState* shared_state =
       to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(transform, output_rect, output_rect, output_rect, false,
-                       false, 1, blend_mode, 0);
+  shared_state->SetAll(transform, output_rect, output_rect, gfx::RRectF(),
+                       output_rect, false, false, 1, blend_mode, 0);
   auto* quad = to_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>();
   gfx::Size arbitrary_nonzero_size(1, 1);
   quad->SetNew(shared_state, output_rect, output_rect, contributing_pass->id,
@@ -171,8 +173,8 @@
 
   viz::SharedQuadState* shared_state =
       to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, false, 1,
-                       SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect, false,
+                       false, 1, SkBlendMode::kSrcOver, 0);
 
   auto* debug_border_quad =
       to_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
@@ -233,8 +235,8 @@
 
   viz::SharedQuadState* shared_state2 =
       to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, false, 1,
-                       SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect, false,
+                       false, 1, SkBlendMode::kSrcOver, 0);
 
   auto* tile_quad = to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   tile_quad->SetNew(shared_state2, rect, visible_rect, needs_blending,
@@ -349,8 +351,8 @@
 
   viz::SharedQuadState* shared_state =
       to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, false, 1,
-                       SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect, false,
+                       false, 1, SkBlendMode::kSrcOver, 0);
 
   viz::DebugBorderDrawQuad* debug_border_quad =
       to_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
@@ -411,8 +413,8 @@
 
   viz::SharedQuadState* shared_state2 =
       to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, false, 1,
-                       SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect, false,
+                       false, 1, SkBlendMode::kSrcOver, 0);
 
   viz::TileDrawQuad* tile_quad =
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 1ac2f04..4a539c7 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -10,7 +10,6 @@
 #include <memory>
 #include <string>
 
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/scheduler/compositor_timing_history.h"
 #include "cc/scheduler/scheduler.h"
@@ -28,8 +27,12 @@
  public:
   static std::unique_ptr<FakeCompositorTimingHistory> Create(
       bool using_synchronous_renderer_compositor);
+  FakeCompositorTimingHistory(const FakeCompositorTimingHistory&) = delete;
   ~FakeCompositorTimingHistory() override;
 
+  FakeCompositorTimingHistory& operator=(const FakeCompositorTimingHistory&) =
+      delete;
+
   void SetAllEstimatesTo(base::TimeDelta duration);
 
   void SetBeginMainFrameQueueDurationCriticalEstimate(base::TimeDelta duration);
@@ -70,9 +73,6 @@
   base::TimeDelta prepare_tiles_duration_;
   base::TimeDelta activate_duration_;
   base::TimeDelta draw_duration_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FakeCompositorTimingHistory);
 };
 
 class TestScheduler : public Scheduler {
@@ -84,6 +84,9 @@
       int layer_tree_host_id,
       base::SingleThreadTaskRunner* task_runner,
       std::unique_ptr<CompositorTimingHistory> compositor_timing_history);
+  TestScheduler(const TestScheduler&) = delete;
+
+  TestScheduler& operator=(const TestScheduler&) = delete;
 
   bool IsDrawThrottled() const { return state_machine_.IsDrawThrottled(); }
 
@@ -137,8 +140,6 @@
 
  private:
   const base::TickClock* now_src_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestScheduler);
 };
 
 }  // namespace cc
diff --git a/cc/test/task_graph_runner_test_template.h b/cc/test/task_graph_runner_test_template.h
index 0384fea1..362eff4 100644
--- a/cc/test/task_graph_runner_test_template.h
+++ b/cc/test/task_graph_runner_test_template.h
@@ -59,6 +59,9 @@
    public:
     FakeTaskImpl(TaskGraphRunnerTestBase* test, int namespace_index, int id)
         : test_(test), namespace_index_(namespace_index), id_(id) {}
+    FakeTaskImpl(const FakeTaskImpl&) = delete;
+
+    FakeTaskImpl& operator=(const FakeTaskImpl&) = delete;
 
     // Overridden from Task:
     void RunOnWorkerThread() override;
@@ -72,8 +75,6 @@
     TaskGraphRunnerTestBase* test_;
     int namespace_index_;
     int id_;
-
-    DISALLOW_COPY_AND_ASSIGN(FakeTaskImpl);
   };
 
   class FakeDependentTaskImpl : public FakeTaskImpl {
@@ -82,14 +83,15 @@
                           int namespace_index,
                           int id)
         : FakeTaskImpl(test, namespace_index, id) {}
+    FakeDependentTaskImpl(const FakeDependentTaskImpl&) = delete;
+
+    FakeDependentTaskImpl& operator=(const FakeDependentTaskImpl&) = delete;
 
     // Overridden from FakeTaskImpl:
     void OnTaskCompleted() override {}
 
    private:
     ~FakeDependentTaskImpl() override {}
-
-    DISALLOW_COPY_AND_ASSIGN(FakeDependentTaskImpl);
   };
 
   TaskGraphRunner* task_graph_runner_;
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h
index 73f32ba..c4af687 100644
--- a/cc/test/test_hooks.h
+++ b/cc/test/test_hooks.h
@@ -5,7 +5,6 @@
 #ifndef CC_TEST_TEST_HOOKS_H_
 #define CC_TEST_TEST_HOOKS_H_
 
-#include "base/macros.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_host_impl.h"
diff --git a/cc/test/test_image_factory.h b/cc/test/test_image_factory.h
index 749c4c7..9178b7b2 100644
--- a/cc/test/test_image_factory.h
+++ b/cc/test/test_image_factory.h
@@ -5,7 +5,6 @@
 #ifndef CC_TEST_TEST_IMAGE_FACTORY_H_
 #define CC_TEST_TEST_IMAGE_FACTORY_H_
 
-#include "base/macros.h"
 #include "gpu/command_buffer/service/image_factory.h"
 
 namespace cc {
@@ -13,8 +12,11 @@
 class TestImageFactory : public gpu::ImageFactory {
  public:
   TestImageFactory();
+  TestImageFactory(const TestImageFactory&) = delete;
   ~TestImageFactory() override;
 
+  TestImageFactory& operator=(const TestImageFactory&) = delete;
+
   // Overridden from gpu::ImageFactory:
   scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer(
       gfx::GpuMemoryBufferHandle handle,
@@ -22,9 +24,6 @@
       gfx::BufferFormat format,
       int client_id,
       gpu::SurfaceHandle surface_handle) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestImageFactory);
 };
 
 }  // namespace cc
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 8254b3b..8600b3b 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/lazy_instance.h"
-#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/viz/common/gpu/context_cache_controller.h"
diff --git a/cc/test/test_task_graph_runner.h b/cc/test/test_task_graph_runner.h
index b0e9bc40..3389269 100644
--- a/cc/test/test_task_graph_runner.h
+++ b/cc/test/test_task_graph_runner.h
@@ -5,7 +5,6 @@
 #ifndef CC_TEST_TEST_TASK_GRAPH_RUNNER_H_
 #define CC_TEST_TEST_TASK_GRAPH_RUNNER_H_
 
-#include "base/macros.h"
 #include "base/threading/simple_thread.h"
 #include "cc/raster/single_thread_task_graph_runner.h"
 
@@ -14,10 +13,10 @@
 class TestTaskGraphRunner : public SingleThreadTaskGraphRunner {
  public:
   TestTaskGraphRunner();
+  TestTaskGraphRunner(const TestTaskGraphRunner&) = delete;
   ~TestTaskGraphRunner() override;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestTaskGraphRunner);
+  TestTaskGraphRunner& operator=(const TestTaskGraphRunner&) = delete;
 };
 
 }  // namespace cc
diff --git a/cc/tiles/checker_image_tracker.h b/cc/tiles/checker_image_tracker.h
index 1a8229fe..f59f5a2 100644
--- a/cc/tiles/checker_image_tracker.h
+++ b/cc/tiles/checker_image_tracker.h
@@ -55,8 +55,11 @@
                       CheckerImageTrackerClient* client,
                       bool enable_checker_imaging,
                       size_t min_image_bytes_to_checker);
+  CheckerImageTracker(const CheckerImageTracker&) = delete;
   ~CheckerImageTracker();
 
+  CheckerImageTracker& operator=(const CheckerImageTracker&) = delete;
+
   // Returns true if the decode for |image| will be deferred to the image decode
   // service and it should be be skipped during raster.
   bool ShouldCheckerImage(const DrawImage& image, WhichTree tree);
@@ -146,13 +149,14 @@
     ScopedDecodeHolder(ImageController* controller,
                        ImageController::ImageDecodeRequestId request_id)
         : controller_(controller), request_id_(request_id) {}
+    ScopedDecodeHolder(const ScopedDecodeHolder&) = delete;
     ~ScopedDecodeHolder() { controller_->UnlockImageDecode(request_id_); }
 
+    ScopedDecodeHolder& operator=(const ScopedDecodeHolder&) = delete;
+
    private:
     ImageController* controller_;
     ImageController::ImageDecodeRequestId request_id_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedDecodeHolder);
   };
 
   void DidFinishImageDecode(PaintImage::Id image_id,
@@ -204,8 +208,6 @@
   base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map_;
 
   base::WeakPtrFactory<CheckerImageTracker> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CheckerImageTracker);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/decoded_image_tracker.h b/cc/tiles/decoded_image_tracker.h
index c88bd2b..a5f99ab 100644
--- a/cc/tiles/decoded_image_tracker.h
+++ b/cc/tiles/decoded_image_tracker.h
@@ -29,8 +29,11 @@
   explicit DecodedImageTracker(
       ImageController* controller,
       scoped_refptr<base::SequencedTaskRunner> task_runner);
+  DecodedImageTracker(const DecodedImageTracker&) = delete;
   ~DecodedImageTracker();
 
+  DecodedImageTracker& operator=(const DecodedImageTracker&) = delete;
+
   // Request that the given image be decoded. This issues a callback upon
   // completion. The callback takes a bool indicating whether the decode was
   // successful or not.
@@ -71,14 +74,16 @@
     ImageLock(DecodedImageTracker* tracker,
               ImageController::ImageDecodeRequestId request_id,
               base::TimeTicks lock_time);
+    ImageLock(const ImageLock&) = delete;
     ~ImageLock();
+
+    ImageLock& operator=(const ImageLock&) = delete;
     base::TimeTicks lock_time() const { return lock_time_; }
 
    private:
     DecodedImageTracker* tracker_;
     ImageController::ImageDecodeRequestId request_id_;
     base::TimeTicks lock_time_;
-    DISALLOW_COPY_AND_ASSIGN(ImageLock);
   };
   base::flat_map<PaintImage::Id, std::unique_ptr<ImageLock>> locked_images_;
   bool timeout_pending_ = false;
@@ -88,8 +93,6 @@
   const base::TickClock* tick_clock_;
 
   base::WeakPtrFactory<DecodedImageTracker> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(DecodedImageTracker);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/eviction_tile_priority_queue.h b/cc/tiles/eviction_tile_priority_queue.h
index 2e76ee8..49ee3ef8 100644
--- a/cc/tiles/eviction_tile_priority_queue.h
+++ b/cc/tiles/eviction_tile_priority_queue.h
@@ -9,7 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/tiles/tile_priority.h"
@@ -21,8 +20,12 @@
 class CC_EXPORT EvictionTilePriorityQueue {
  public:
   EvictionTilePriorityQueue();
+  EvictionTilePriorityQueue(const EvictionTilePriorityQueue&) = delete;
   ~EvictionTilePriorityQueue();
 
+  EvictionTilePriorityQueue& operator=(const EvictionTilePriorityQueue&) =
+      delete;
+
   void Build(const std::vector<PictureLayerImpl*>& active_layers,
              const std::vector<PictureLayerImpl*>& pending_layers,
              TreePriority tree_priority);
@@ -39,8 +42,6 @@
   std::vector<std::unique_ptr<TilingSetEvictionQueue>> active_queues_;
   std::vector<std::unique_ptr<TilingSetEvictionQueue>> pending_queues_;
   TreePriority tree_priority_;
-
-  DISALLOW_COPY_AND_ASSIGN(EvictionTilePriorityQueue);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/frame_viewer_instrumentation.h b/cc/tiles/frame_viewer_instrumentation.h
index 2f389be..7c4ad9d 100644
--- a/cc/tiles/frame_viewer_instrumentation.h
+++ b/cc/tiles/frame_viewer_instrumentation.h
@@ -5,7 +5,6 @@
 #ifndef CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_
 #define CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_
 
-#include "base/macros.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/tiles/tile_priority.h"
 
@@ -25,10 +24,10 @@
                     TileResolution tile_resolution,
                     int source_frame_number,
                     int layer_id);
+  ScopedAnalyzeTask(const ScopedAnalyzeTask&) = delete;
   ~ScopedAnalyzeTask();
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedAnalyzeTask);
+  ScopedAnalyzeTask& operator=(const ScopedAnalyzeTask&) = delete;
 };
 
 class ScopedRasterTask {
@@ -37,10 +36,10 @@
                    TileResolution tile_resolution,
                    int source_frame_number,
                    int layer_id);
+  ScopedRasterTask(const ScopedRasterTask&) = delete;
   ~ScopedRasterTask();
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedRasterTask);
+  ScopedRasterTask& operator=(const ScopedRasterTask&) = delete;
 };
 
 bool IsTracingLayerTreeSnapshots();
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index 89fc519..4f583e1e 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -477,6 +477,9 @@
         task_type_(task_type) {
     DCHECK(!SkipImage(draw_image));
   }
+  GpuImageDecodeTaskImpl(const GpuImageDecodeTaskImpl&) = delete;
+
+  GpuImageDecodeTaskImpl& operator=(const GpuImageDecodeTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
@@ -503,8 +506,6 @@
   DrawImage image_;
   const ImageDecodeCache::TracingInfo tracing_info_;
   const GpuImageDecodeCache::DecodeTaskType task_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuImageDecodeTaskImpl);
 };
 
 // Task which creates an image from decoded data. Typically this involves
@@ -526,6 +527,9 @@
     if (decode_dependency)
       dependencies_.push_back(std::move(decode_dependency));
   }
+  ImageUploadTaskImpl(const ImageUploadTaskImpl&) = delete;
+
+  ImageUploadTaskImpl& operator=(const ImageUploadTaskImpl&) = delete;
 
   // Override from Task:
   void RunOnWorkerThread() override {
@@ -546,8 +550,6 @@
   GpuImageDecodeCache* cache_;
   DrawImage image_;
   const ImageDecodeCache::TracingInfo tracing_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageUploadTaskImpl);
 };
 
 GpuImageDecodeCache::ImageDataBase::ImageDataBase() = default;
diff --git a/cc/tiles/image_controller.h b/cc/tiles/image_controller.h
index d554010..2533b6e 100644
--- a/cc/tiles/image_controller.h
+++ b/cc/tiles/image_controller.h
@@ -10,7 +10,6 @@
 
 #include "base/callback.h"
 #include "base/containers/flat_map.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
@@ -34,8 +33,11 @@
   explicit ImageController(
       base::SequencedTaskRunner* origin_task_runner,
       scoped_refptr<base::SequencedTaskRunner> worker_task_runner);
+  ImageController(const ImageController&) = delete;
   virtual ~ImageController();
 
+  ImageController& operator=(const ImageController&) = delete;
+
   void SetImageDecodeCache(ImageDecodeCache* cache);
   void SetPaintWorkletLayerPainter(
       std::unique_ptr<PaintWorkletLayerPainter> painter);
@@ -150,8 +152,6 @@
   std::vector<ImageDecodeRequest> orphaned_decode_requests_;
 
   base::WeakPtrFactory<ImageController> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageController);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/image_controller_unittest.cc b/cc/tiles/image_controller_unittest.cc
index ba11ee8..05c82a4 100644
--- a/cc/tiles/image_controller_unittest.cc
+++ b/cc/tiles/image_controller_unittest.cc
@@ -161,6 +161,9 @@
   SimpleTask() : TileTask(true /* supports_concurrent_execution */) {
     EXPECT_TRUE(thread_checker_.CalledOnValidThread());
   }
+  SimpleTask(const SimpleTask&) = delete;
+
+  SimpleTask& operator=(const SimpleTask&) = delete;
 
   void RunOnWorkerThread() override {
     EXPECT_FALSE(HasCompleted());
@@ -177,8 +180,6 @@
 
   base::ThreadChecker thread_checker_;
   bool has_run_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleTask);
 };
 
 // A task that blocks until instructed otherwise.
@@ -188,6 +189,9 @@
       : TileTask(true /* supports_concurrent_execution */), run_cv_(&lock_) {
     EXPECT_TRUE(thread_checker_.CalledOnValidThread());
   }
+  BlockingTask(const BlockingTask&) = delete;
+
+  BlockingTask& operator=(const BlockingTask&) = delete;
 
   void RunOnWorkerThread() override {
     EXPECT_FALSE(HasCompleted());
@@ -219,8 +223,6 @@
   base::Lock lock_;
   base::ConditionVariable run_cv_;
   bool can_run_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(BlockingTask);
 };
 
 // For tests that exercise image controller's thread, this is the timeout value
diff --git a/cc/tiles/paint_worklet_image_cache.cc b/cc/tiles/paint_worklet_image_cache.cc
index fc37da4a..9eecf2b 100644
--- a/cc/tiles/paint_worklet_image_cache.cc
+++ b/cc/tiles/paint_worklet_image_cache.cc
@@ -14,6 +14,9 @@
   PaintWorkletTaskImpl(PaintWorkletImageCache* cache,
                        const PaintImage& paint_image)
       : TileTask(true), cache_(cache), paint_image_(paint_image) {}
+  PaintWorkletTaskImpl(const PaintWorkletTaskImpl&) = delete;
+
+  PaintWorkletTaskImpl& operator=(const PaintWorkletTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override { cache_->PaintImageInTask(paint_image_); }
@@ -27,8 +30,6 @@
  private:
   PaintWorkletImageCache* cache_;
   PaintImage paint_image_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintWorkletTaskImpl);
 };
 
 PaintWorkletImageCache::PaintWorkletImageCache() {}
diff --git a/cc/tiles/picture_layer_tiling.h b/cc/tiles/picture_layer_tiling.h
index d9c33a0..4f66d99 100644
--- a/cc/tiles/picture_layer_tiling.h
+++ b/cc/tiles/picture_layer_tiling.h
@@ -14,7 +14,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/base/region.h"
 #include "cc/base/tiling_data.h"
 #include "cc/cc_export.h"
@@ -95,8 +94,11 @@
                      PictureLayerTilingClient* client,
                      float min_preraster_distance,
                      float max_preraster_distance);
+  PictureLayerTiling(const PictureLayerTiling&) = delete;
   ~PictureLayerTiling();
 
+  PictureLayerTiling& operator=(const PictureLayerTiling&) = delete;
+
   PictureLayerTilingClient* client() const { return client_; }
 
   void SetRasterSourceAndResize(scoped_refptr<RasterSource> raster_source);
@@ -392,9 +394,6 @@
   bool has_soon_border_rect_tiles_ = false;
   bool has_eventually_rect_tiles_ = false;
   bool all_tiles_done_ = true;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PictureLayerTiling);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/picture_layer_tiling_set.h b/cc/tiles/picture_layer_tiling_set.h
index 78e426e..b5b9c453 100644
--- a/cc/tiles/picture_layer_tiling_set.h
+++ b/cc/tiles/picture_layer_tiling_set.h
@@ -11,7 +11,6 @@
 #include <set>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/base/region.h"
 #include "cc/tiles/picture_layer_tiling.h"
 #include "ui/gfx/geometry/size.h"
@@ -48,8 +47,11 @@
       int skewport_extrapolation_limit_in_screen_pixels,
       float max_preraster_distance);
 
+  PictureLayerTilingSet(const PictureLayerTilingSet&) = delete;
   ~PictureLayerTilingSet();
 
+  PictureLayerTilingSet& operator=(const PictureLayerTilingSet&) = delete;
+
   const PictureLayerTilingClient* client() const { return client_; }
 
   void CleanUpTilings(float min_acceptable_high_res_scale_key,
@@ -262,9 +264,6 @@
   gfx::Rect eventually_rect_in_layer_space_;
 
   friend class Iterator;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingSet);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/picture_layer_tiling_unittest.cc b/cc/tiles/picture_layer_tiling_unittest.cc
index 4a98325e..424dc99 100644
--- a/cc/tiles/picture_layer_tiling_unittest.cc
+++ b/cc/tiles/picture_layer_tiling_unittest.cc
@@ -10,7 +10,6 @@
 #include <set>
 
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/base/math_util.h"
 #include "cc/test/fake_output_surface_client.h"
@@ -90,8 +89,13 @@
       base::RepeatingCallback<void(Tile* tile, const gfx::Rect& geometry_rect)>;
 
   PictureLayerTilingIteratorTest() = default;
+  PictureLayerTilingIteratorTest(const PictureLayerTilingIteratorTest&) =
+      delete;
   ~PictureLayerTilingIteratorTest() override = default;
 
+  PictureLayerTilingIteratorTest& operator=(
+      const PictureLayerTilingIteratorTest&) = delete;
+
   void Initialize(const gfx::Size& tile_size,
                   float contents_scale,
                   const gfx::Size& layer_bounds) {
@@ -218,9 +222,6 @@
   FakePictureLayerTilingClient client_;
   std::unique_ptr<TestablePictureLayerTiling> tiling_;
   bool loose_texel_extent_check_ = false;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingIteratorTest);
 };
 
 TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
diff --git a/cc/tiles/raster_tile_priority_queue.h b/cc/tiles/raster_tile_priority_queue.h
index 9886076..7bfc229 100644
--- a/cc/tiles/raster_tile_priority_queue.h
+++ b/cc/tiles/raster_tile_priority_queue.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/tiles/tile_priority.h"
@@ -26,6 +25,9 @@
       Type type);
 
   virtual ~RasterTilePriorityQueue() {}
+  RasterTilePriorityQueue(const RasterTilePriorityQueue&) = delete;
+
+  RasterTilePriorityQueue& operator=(const RasterTilePriorityQueue&) = delete;
 
   virtual bool IsEmpty() const = 0;
   virtual const PrioritizedTile& Top() const = 0;
@@ -33,9 +35,6 @@
 
  protected:
   RasterTilePriorityQueue() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueue);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/raster_tile_priority_queue_all.h b/cc/tiles/raster_tile_priority_queue_all.h
index 698dfe0..5aa6caf 100644
--- a/cc/tiles/raster_tile_priority_queue_all.h
+++ b/cc/tiles/raster_tile_priority_queue_all.h
@@ -9,7 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/tiles/raster_tile_priority_queue.h"
@@ -21,8 +20,12 @@
 class CC_EXPORT RasterTilePriorityQueueAll : public RasterTilePriorityQueue {
  public:
   RasterTilePriorityQueueAll();
+  RasterTilePriorityQueueAll(const RasterTilePriorityQueueAll&) = delete;
   ~RasterTilePriorityQueueAll() override;
 
+  RasterTilePriorityQueueAll& operator=(const RasterTilePriorityQueueAll&) =
+      delete;
+
   bool IsEmpty() const override;
   const PrioritizedTile& Top() const override;
   void Pop() override;
@@ -41,8 +44,6 @@
   std::vector<std::unique_ptr<TilingSetRasterQueueAll>> active_queues_;
   std::vector<std::unique_ptr<TilingSetRasterQueueAll>> pending_queues_;
   TreePriority tree_priority_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueueAll);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/raster_tile_priority_queue_required.h b/cc/tiles/raster_tile_priority_queue_required.h
index a45a4ba..c405e25 100644
--- a/cc/tiles/raster_tile_priority_queue_required.h
+++ b/cc/tiles/raster_tile_priority_queue_required.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/tiles/raster_tile_priority_queue.h"
 #include "cc/tiles/tiling_set_raster_queue_required.h"
@@ -18,8 +17,13 @@
 class RasterTilePriorityQueueRequired : public RasterTilePriorityQueue {
  public:
   RasterTilePriorityQueueRequired();
+  RasterTilePriorityQueueRequired(const RasterTilePriorityQueueRequired&) =
+      delete;
   ~RasterTilePriorityQueueRequired() override;
 
+  RasterTilePriorityQueueRequired& operator=(
+      const RasterTilePriorityQueueRequired&) = delete;
+
   bool IsEmpty() const override;
   const PrioritizedTile& Top() const override;
   void Pop() override;
@@ -37,8 +41,6 @@
       const std::vector<PictureLayerImpl*>& pending_layers);
 
   std::vector<std::unique_ptr<TilingSetRasterQueueRequired>> tiling_set_queues_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueueRequired);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc
index 126cb37b..c2bb32f6 100644
--- a/cc/tiles/software_image_decode_cache.cc
+++ b/cc/tiles/software_image_decode_cache.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/format_macros.h"
-#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -64,6 +63,10 @@
         paint_image_(paint_image),
         task_type_(task_type),
         tracing_info_(tracing_info) {}
+  SoftwareImageDecodeTaskImpl(const SoftwareImageDecodeTaskImpl&) = delete;
+
+  SoftwareImageDecodeTaskImpl& operator=(const SoftwareImageDecodeTaskImpl&) =
+      delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
@@ -91,8 +94,6 @@
   PaintImage paint_image_;
   SoftwareImageDecodeCache::DecodeTaskType task_type_;
   const ImageDecodeCache::TracingInfo tracing_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(SoftwareImageDecodeTaskImpl);
 };
 
 SkSize GetScaleAdjustment(const SoftwareImageDecodeCache::CacheKey& key) {
diff --git a/cc/tiles/tile.h b/cc/tiles/tile.h
index d413c3c0..84f68cb 100644
--- a/cc/tiles/tile.h
+++ b/cc/tiles/tile.h
@@ -8,7 +8,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/paint/draw_image.h"
 #include "cc/raster/tile_task.h"
@@ -51,8 +50,11 @@
 
   typedef uint64_t Id;
 
+  Tile(const Tile&) = delete;
   ~Tile();
 
+  Tile& operator=(const Tile&) = delete;
+
   Id id() const {
     return id_;
   }
@@ -180,8 +182,6 @@
   // rasterize a resource with checker images.
   bool raster_task_scheduled_with_checker_images_ = false;
   scoped_refptr<TileTask> raster_task_;
-
-  DISALLOW_COPY_AND_ASSIGN(Tile);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 43d282e6..e797e6db 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -14,7 +14,6 @@
 #include "base/bind.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/metrics/histogram.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
@@ -83,8 +82,11 @@
       : playback_image_provider_(std::move(playback_image_provider)),
         paint_worklet_image_provider_(std::move(paint_worklet_image_provider)) {
   }
+  DispatchingImageProvider(const DispatchingImageProvider&) = delete;
   ~DispatchingImageProvider() override = default;
 
+  DispatchingImageProvider& operator=(const DispatchingImageProvider&) = delete;
+
   DispatchingImageProvider(DispatchingImageProvider&& other) = default;
 
   ImageProvider::ScopedResult GetRasterContent(
@@ -98,8 +100,6 @@
  private:
   PlaybackImageProvider playback_image_provider_;
   PaintWorkletImageProvider paint_worklet_image_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(DispatchingImageProvider);
 };
 
 class RasterTaskImpl : public TileTask {
@@ -139,6 +139,8 @@
     DCHECK(origin_thread_checker_.CalledOnValidThread());
     playback_settings_.image_provider = &image_provider_;
   }
+  RasterTaskImpl(const RasterTaskImpl&) = delete;
+  RasterTaskImpl& operator=(const RasterTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
@@ -205,8 +207,6 @@
   std::unique_ptr<RasterBuffer> raster_buffer_;
   DispatchingImageProvider image_provider_;
   GURL url_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl);
 };
 
 TaskCategory TaskCategoryForTileTask(TileTask* task,
@@ -334,6 +334,8 @@
         task_runner_(task_runner),
         on_task_set_finished_callback_(
             std::move(on_task_set_finished_callback)) {}
+  TaskSetFinishedTaskImpl(const TaskSetFinishedTaskImpl&) = delete;
+  TaskSetFinishedTaskImpl& operator=(const TaskSetFinishedTaskImpl&) = delete;
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
@@ -354,8 +356,6 @@
  private:
   base::SequencedTaskRunner* task_runner_;
   const base::RepeatingClosure on_task_set_finished_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaskSetFinishedTaskImpl);
 };
 
 class DidFinishRunningAllTilesTask : public TileTask {
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index c4024e2..30d5590 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -14,7 +14,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/sequenced_task_runner.h"
 #include "base/values.h"
 #include "cc/base/unique_notifier.h"
@@ -135,8 +134,12 @@
               scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner,
               size_t scheduled_raster_task_limit,
               const TileManagerSettings& tile_manager_settings);
+
+  TileManager(const TileManager&) = delete;
   ~TileManager() override;
 
+  TileManager& operator=(const TileManager&) = delete;
+
   // Assigns tile memory and schedules work to prepare tiles for drawing.
   // This step occurs after Commit and at most once per BeginFrame. It can be
   // called on its own, that is, outside of Commit.
@@ -470,8 +473,6 @@
   base::WeakPtrFactory<TileManager> task_set_finished_weak_ptr_factory_;
   // The |ready_to_draw_callback_weak_ptr_factory_| is never invalidated.
   base::WeakPtrFactory<TileManager> ready_to_draw_callback_weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(TileManager);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/tile_task_manager.h b/cc/tiles/tile_task_manager.h
index 7f543c1..f77a460 100644
--- a/cc/tiles/tile_task_manager.h
+++ b/cc/tiles/tile_task_manager.h
@@ -36,8 +36,11 @@
 
 class CC_EXPORT TileTaskManagerImpl : public TileTaskManager {
  public:
+  TileTaskManagerImpl(const TileTaskManagerImpl&) = delete;
   ~TileTaskManagerImpl() override;
 
+  TileTaskManagerImpl& operator=(const TileTaskManagerImpl&) = delete;
+
   static std::unique_ptr<TileTaskManagerImpl> Create(
       TaskGraphRunner* task_graph_runner);
 
@@ -51,9 +54,6 @@
 
   TaskGraphRunner* task_graph_runner_;
   const NamespaceToken namespace_token_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TileTaskManagerImpl);
 };
 
 }  // namespace cc
diff --git a/cc/tiles/tiling_set_raster_queue_all.h b/cc/tiles/tiling_set_raster_queue_all.h
index e29736d..7e9149f3 100644
--- a/cc/tiles/tiling_set_raster_queue_all.h
+++ b/cc/tiles/tiling_set_raster_queue_all.h
@@ -8,7 +8,6 @@
 #include <stddef.h>
 
 #include "base/containers/stack_container.h"
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/tiles/picture_layer_tiling_set.h"
 #include "cc/tiles/prioritized_tile.h"
@@ -24,8 +23,11 @@
   TilingSetRasterQueueAll(PictureLayerTilingSet* tiling_set,
                           bool prioritize_low_res,
                           bool is_drawing_layer);
+  TilingSetRasterQueueAll(const TilingSetRasterQueueAll&) = delete;
   ~TilingSetRasterQueueAll();
 
+  TilingSetRasterQueueAll& operator=(const TilingSetRasterQueueAll&) = delete;
+
   const PrioritizedTile& Top() const;
   void Pop();
   bool IsEmpty() const;
@@ -193,8 +195,6 @@
   base::StackVector<IterationStage, 6> stages_;
   TilingIterator iterators_[NUM_ITERATORS];
   bool is_drawing_layer_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(TilingSetRasterQueueAll);
 };
 
 }  // namespace cc
diff --git a/cc/trees/damage_tracker.h b/cc/trees/damage_tracker.h
index c320db43..bda7579c 100644
--- a/cc/trees/damage_tracker.h
+++ b/cc/trees/damage_tracker.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer_collections.h"
 #include "ui/gfx/geometry/rect.h"
@@ -30,8 +29,11 @@
 class CC_EXPORT DamageTracker {
  public:
   static std::unique_ptr<DamageTracker> Create();
+  DamageTracker(const DamageTracker&) = delete;
   ~DamageTracker();
 
+  DamageTracker& operator=(const DamageTracker&) = delete;
+
   static void UpdateDamageTracking(
       LayerTreeImpl* layer_tree_impl,
       const RenderSurfaceList& render_surface_list);
@@ -153,8 +155,6 @@
 
   // Damage accumulated since the last call to PrepareForUpdate().
   DamageAccumulator damage_for_this_update_;
-
-  DISALLOW_COPY_AND_ASSIGN(DamageTracker);
 };
 
 }  // namespace cc
diff --git a/cc/trees/debug_rect_history.h b/cc/trees/debug_rect_history.h
index fb6b9021..94d1ee9 100644
--- a/cc/trees/debug_rect_history.h
+++ b/cc/trees/debug_rect_history.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/input/touch_action.h"
 #include "cc/layers/layer_collections.h"
 #include "ui/gfx/geometry/rect.h"
@@ -71,8 +70,11 @@
  public:
   static std::unique_ptr<DebugRectHistory> Create();
 
+  DebugRectHistory(const DebugRectHistory&) = delete;
   ~DebugRectHistory();
 
+  DebugRectHistory& operator=(const DebugRectHistory&) = delete;
+
   // Note: Saving debug rects must happen before layers' change tracking is
   // reset.
   void SaveDebugRectsForCurrentFrame(
@@ -99,8 +101,6 @@
   void SaveNonFastScrollableRectsCallback(LayerImpl* layer);
 
   std::vector<DebugRect> debug_rects_;
-
-  DISALLOW_COPY_AND_ASSIGN(DebugRectHistory);
 };
 
 }  // namespace cc
diff --git a/cc/trees/frame_rate_counter.h b/cc/trees/frame_rate_counter.h
index 2eadf84..8646150 100644
--- a/cc/trees/frame_rate_counter.h
+++ b/cc/trees/frame_rate_counter.h
@@ -10,7 +10,6 @@
 #include <memory>
 
 #include "base/containers/ring_buffer.h"
-#include "base/macros.h"
 #include "base/time/time.h"
 
 namespace cc {
@@ -21,6 +20,9 @@
  public:
   static std::unique_ptr<FrameRateCounter> Create(bool has_impl_thread);
 
+  FrameRateCounter(const FrameRateCounter&) = delete;
+  FrameRateCounter& operator=(const FrameRateCounter&) = delete;
+
   size_t current_frame_number() const { return ring_buffer_.CurrentIndex(); }
   int dropped_frame_count() const { return dropped_frame_count_; }
   size_t time_stamp_history_size() const { return ring_buffer_.BufferSize(); }
@@ -51,8 +53,6 @@
 
   bool has_impl_thread_;
   int dropped_frame_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(FrameRateCounter);
 };
 
 }  // namespace cc
diff --git a/cc/trees/image_animation_controller.h b/cc/trees/image_animation_controller.h
index d6f6c3c..a95ec124 100644
--- a/cc/trees/image_animation_controller.h
+++ b/cc/trees/image_animation_controller.h
@@ -133,10 +133,13 @@
   class AnimationState {
    public:
     AnimationState();
+    AnimationState(const AnimationState&) = delete;
     AnimationState(AnimationState&& other);
-    AnimationState& operator=(AnimationState&& other);
     ~AnimationState();
 
+    AnimationState& operator=(const AnimationState&) = delete;
+    AnimationState& operator=(AnimationState&& other);
+
     bool ShouldAnimate() const;
     bool AdvanceFrame(const viz::BeginFrameArgs& args,
                       bool enable_image_animation_resync);
@@ -224,8 +227,6 @@
     // The number of frames skipped during catch-up the last time this animation
     // was advanced.
     size_t last_num_frames_skipped_ = 0u;
-
-    DISALLOW_COPY_AND_ASSIGN(AnimationState);
   };
 
   class InvalidationScheduler {
diff --git a/cc/trees/layer_tree_frame_sink.cc b/cc/trees/layer_tree_frame_sink.cc
index 024981c..71ed277 100644
--- a/cc/trees/layer_tree_frame_sink.cc
+++ b/cc/trees/layer_tree_frame_sink.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/trees/layer_tree_frame_sink_client.h"
@@ -25,8 +24,11 @@
   ContextLostForwarder(base::WeakPtr<LayerTreeFrameSink> frame_sink,
                        scoped_refptr<base::SingleThreadTaskRunner> task_runner)
       : frame_sink_(frame_sink), task_runner_(std::move(task_runner)) {}
+  ContextLostForwarder(const ContextLostForwarder&) = delete;
   ~ContextLostForwarder() override = default;
 
+  ContextLostForwarder& operator=(const ContextLostForwarder&) = delete;
+
   void OnContextLost() override {
     task_runner_->PostTask(
         FROM_HERE,
@@ -36,7 +38,6 @@
  private:
   base::WeakPtr<LayerTreeFrameSink> frame_sink_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  DISALLOW_COPY_AND_ASSIGN(ContextLostForwarder);
 };
 
 LayerTreeFrameSink::LayerTreeFrameSink(
diff --git a/cc/trees/layer_tree_frame_sink.h b/cc/trees/layer_tree_frame_sink.h
index 7ae114e3..76634a7 100644
--- a/cc/trees/layer_tree_frame_sink.h
+++ b/cc/trees/layer_tree_frame_sink.h
@@ -8,7 +8,6 @@
 #include <deque>
 #include <memory>
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
@@ -59,9 +58,12 @@
       scoped_refptr<viz::RasterContextProvider> worker_context_provider,
       scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
       gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+  LayerTreeFrameSink(const LayerTreeFrameSink&) = delete;
 
   ~LayerTreeFrameSink() override;
 
+  LayerTreeFrameSink& operator=(const LayerTreeFrameSink&) = delete;
+
   base::WeakPtr<LayerTreeFrameSink> GetWeakPtr();
 
   // Called by the compositor on the compositor thread. This is a place where
@@ -153,7 +155,6 @@
  private:
   THREAD_CHECKER(thread_checker_);
   base::WeakPtrFactory<LayerTreeFrameSink> weak_ptr_factory_;
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeFrameSink);
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index ec6298d..3ec2655 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -19,7 +19,6 @@
 #include "base/cancelable_callback.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
@@ -128,8 +127,11 @@
       LayerTreeHostSingleThreadClient* single_thread_client,
       InitParams params);
 
+  LayerTreeHost(const LayerTreeHost&) = delete;
   virtual ~LayerTreeHost();
 
+  LayerTreeHost& operator=(const LayerTreeHost&) = delete;
+
   // Returns the process global unique identifier for this LayerTreeHost.
   int GetId() const;
 
@@ -893,8 +895,6 @@
   // Used to vend weak pointers to LayerTreeHost to ScopedDeferMainFrameUpdate
   // objects.
   base::WeakPtrFactory<LayerTreeHost> defer_main_frame_update_weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index 235910b..fab5e1eb 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "cc/cc_export.h"
 #include "cc/input/browser_controls_state.h"
@@ -158,8 +157,11 @@
 
 struct CC_EXPORT ScrollAndScaleSet {
   ScrollAndScaleSet();
+  ScrollAndScaleSet(const ScrollAndScaleSet&) = delete;
   ~ScrollAndScaleSet();
 
+  ScrollAndScaleSet& operator=(const ScrollAndScaleSet&) = delete;
+
   // The inner viewport scroll delta is kept separate since it's special.
   // Because the inner (visual) viewport's maximum offset depends on the
   // current page scale, the two must be committed at the same time to prevent
@@ -192,9 +194,6 @@
   // Set to true when a scroll gesture being handled on the compositor has
   // ended.
   bool scroll_gesture_did_end;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScrollAndScaleSet);
 };
 
 template <typename Function>
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 0a875e9..e3c7641d 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -906,9 +906,9 @@
   viz::SharedQuadState* shared_quad_state =
       target_render_pass->CreateAndAppendSharedQuadState();
   shared_quad_state->SetAll(gfx::Transform(), root_target_rect,
-                            root_target_rect, root_target_rect, false,
-                            are_contents_opaque, opacity, SkBlendMode::kSrcOver,
-                            sorting_context_id);
+                            root_target_rect, gfx::RRectF(), root_target_rect,
+                            false, are_contents_opaque, opacity,
+                            SkBlendMode::kSrcOver, sorting_context_id);
 
   for (gfx::Rect screen_space_rect : fill_region) {
     gfx::Rect visible_screen_space_rect = screen_space_rect;
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 6f07f25..7cac46c 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -17,7 +17,6 @@
 #include "base/callback.h"
 #include "base/containers/circular_deque.h"
 #include "base/containers/flat_map.h"
-#include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/sequenced_task_runner.h"
 #include "base/time/time.h"
@@ -184,7 +183,10 @@
   // or become part of the CompositorFrameMetadata.
   struct CC_EXPORT FrameData {
     FrameData();
+    FrameData(const FrameData&) = delete;
     ~FrameData();
+
+    FrameData& operator=(const FrameData&) = delete;
     void AsValueInto(base::trace_event::TracedValue* value) const;
 
     std::vector<viz::SurfaceId> activation_dependencies;
@@ -196,17 +198,17 @@
     bool has_no_damage = false;
     bool may_contain_video = false;
     viz::BeginFrameAck begin_frame_ack;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(FrameData);
   };
 
   // A struct of data for a single UIResource, including the backing
   // pixels, and metadata about it.
   struct CC_EXPORT UIResourceData {
     UIResourceData();
-    ~UIResourceData();
+    UIResourceData(const UIResourceData&) = delete;
     UIResourceData(UIResourceData&&) noexcept;
+    ~UIResourceData();
+
+    UIResourceData& operator=(const UIResourceData&) = delete;
     UIResourceData& operator=(UIResourceData&&);
 
     bool opaque;
@@ -221,9 +223,6 @@
     // The name with which to refer to the resource in frames submitted to the
     // display compositor.
     viz::ResourceId resource_id_for_export;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(UIResourceData);
   };
 
   static std::unique_ptr<LayerTreeHostImpl> Create(
@@ -235,8 +234,11 @@
       std::unique_ptr<MutatorHost> mutator_host,
       int id,
       scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner);
+  LayerTreeHostImpl(const LayerTreeHostImpl&) = delete;
   ~LayerTreeHostImpl() override;
 
+  LayerTreeHostImpl& operator=(const LayerTreeHostImpl&) = delete;
+
   // InputHandler implementation
   void BindToClient(InputHandlerClient* client) override;
   InputHandler::ScrollStatus ScrollBegin(
@@ -1114,9 +1116,13 @@
         uint32_t token,
         base::TimeTicks cc_frame_time,
         std::vector<LayerTreeHost::PresentationTimeCallback> callbacks);
+    FrameTokenInfo(const FrameTokenInfo&) = delete;
     FrameTokenInfo(FrameTokenInfo&&);
     ~FrameTokenInfo();
 
+    FrameTokenInfo& operator=(const FrameTokenInfo&) = delete;
+    FrameTokenInfo& operator=(FrameTokenInfo&&) = default;
+
     uint32_t token;
 
     // The compositor frame time used to produce the frame.
@@ -1124,8 +1130,6 @@
 
     // The callbacks to send back to the main thread.
     std::vector<LayerTreeHost::PresentationTimeCallback> callbacks;
-
-    DISALLOW_COPY_AND_ASSIGN(FrameTokenInfo);
   };
 
   base::circular_deque<FrameTokenInfo> frame_token_infos_;
@@ -1143,8 +1147,6 @@
   // Set in ScrollEnd before clearing the currently scrolling node. This is
   // used to send the scrollend DOM event when scrolling has happened on CC.
   ElementId last_scroller_element_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 3c91b797..d0d2a54 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -13879,8 +13879,13 @@
  public:
   explicit TestRenderFrameMetadataObserver(bool increment_counter)
       : increment_counter_(increment_counter) {}
+  TestRenderFrameMetadataObserver(const TestRenderFrameMetadataObserver&) =
+      delete;
   ~TestRenderFrameMetadataObserver() override {}
 
+  TestRenderFrameMetadataObserver& operator=(
+      const TestRenderFrameMetadataObserver&) = delete;
+
   void BindToCurrentThread() override {}
   void OnRenderFrameSubmission(
       const RenderFrameMetadata& render_frame_metadata,
@@ -13898,8 +13903,6 @@
  private:
   bool increment_counter_;
   base::Optional<RenderFrameMetadata> last_metadata_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestRenderFrameMetadataObserver);
 };
 
 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToRenderFrameMetadata) {
diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc
index 1443be7..399b68f 100644
--- a/cc/trees/layer_tree_host_unittest_proxy.cc
+++ b/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -4,7 +4,6 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_picture_layer.h"
 #include "cc/test/layer_tree_test.h"
@@ -39,8 +38,13 @@
 class LayerTreeHostProxyTestSetNeedsCommit : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestSetNeedsCommit() = default;
+  LayerTreeHostProxyTestSetNeedsCommit(
+      const LayerTreeHostProxyTestSetNeedsCommit&) = delete;
   ~LayerTreeHostProxyTestSetNeedsCommit() override = default;
 
+  LayerTreeHostProxyTestSetNeedsCommit& operator=(
+      const LayerTreeHostProxyTestSetNeedsCommit&) = delete;
+
   void BeginTest() override {
     EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
               GetProxyMain()->max_requested_pipeline_stage());
@@ -66,9 +70,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsCommit);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsCommit);
@@ -76,8 +77,13 @@
 class LayerTreeHostProxyTestSetNeedsAnimate : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestSetNeedsAnimate() = default;
+  LayerTreeHostProxyTestSetNeedsAnimate(
+      const LayerTreeHostProxyTestSetNeedsAnimate&) = delete;
   ~LayerTreeHostProxyTestSetNeedsAnimate() override = default;
 
+  LayerTreeHostProxyTestSetNeedsAnimate& operator=(
+      const LayerTreeHostProxyTestSetNeedsAnimate&) = delete;
+
   void BeginTest() override {
     EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
               GetProxyMain()->max_requested_pipeline_stage());
@@ -101,9 +107,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsAnimate);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsAnimate);
@@ -112,8 +115,13 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestSetNeedsUpdateLayers() = default;
+  LayerTreeHostProxyTestSetNeedsUpdateLayers(
+      const LayerTreeHostProxyTestSetNeedsUpdateLayers&) = delete;
   ~LayerTreeHostProxyTestSetNeedsUpdateLayers() override = default;
 
+  LayerTreeHostProxyTestSetNeedsUpdateLayers& operator=(
+      const LayerTreeHostProxyTestSetNeedsUpdateLayers&) = delete;
+
   void BeginTest() override {
     EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
               GetProxyMain()->max_requested_pipeline_stage());
@@ -137,9 +145,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsUpdateLayers);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsUpdateLayers);
@@ -148,9 +153,14 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() = default;
+  LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating(
+      const LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating&) = delete;
   ~LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() override =
       default;
 
+  LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating& operator=(
+      const LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating&) = delete;
+
   void BeginTest() override { proxy()->SetNeedsAnimate(); }
 
   void WillBeginMainFrame() override {
@@ -182,10 +192,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating);
@@ -194,8 +200,13 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() = default;
+  LayerTreeHostProxyTestSetNeedsCommitWhileAnimating(
+      const LayerTreeHostProxyTestSetNeedsCommitWhileAnimating&) = delete;
   ~LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() override = default;
 
+  LayerTreeHostProxyTestSetNeedsCommitWhileAnimating& operator=(
+      const LayerTreeHostProxyTestSetNeedsCommitWhileAnimating&) = delete;
+
   void BeginTest() override { proxy()->SetNeedsAnimate(); }
 
   void WillBeginMainFrame() override {
@@ -227,9 +238,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsCommitWhileAnimating);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsCommitWhileAnimating);
@@ -238,6 +246,11 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestCommitWaitsForActivation() = default;
+  LayerTreeHostProxyTestCommitWaitsForActivation(
+      const LayerTreeHostProxyTestCommitWaitsForActivation&) = delete;
+
+  LayerTreeHostProxyTestCommitWaitsForActivation& operator=(
+      const LayerTreeHostProxyTestCommitWaitsForActivation&) = delete;
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
@@ -314,8 +327,6 @@
  private:
   base::Lock activate_blocked_lock_;
   bool activate_blocked_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestCommitWaitsForActivation);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestCommitWaitsForActivation);
@@ -328,6 +339,11 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestCommitWaitsForActivationMFBA() = default;
+  LayerTreeHostProxyTestCommitWaitsForActivationMFBA(
+      const LayerTreeHostProxyTestCommitWaitsForActivationMFBA&) = delete;
+
+  LayerTreeHostProxyTestCommitWaitsForActivationMFBA& operator=(
+      const LayerTreeHostProxyTestCommitWaitsForActivationMFBA&) = delete;
 
   void InitializeSettings(LayerTreeSettings* settings) override {
     settings->main_frame_before_activation_enabled = true;
@@ -419,8 +435,6 @@
  private:
   base::Lock activate_blocked_lock_;
   bool activate_blocked_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestCommitWaitsForActivationMFBA);
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostProxyTestCommitWaitsForActivationMFBA);
@@ -431,6 +445,10 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestImplFrameCausesAnimatePending() = default;
+  LayerTreeHostProxyTestImplFrameCausesAnimatePending(
+      const LayerTreeHostProxyTestImplFrameCausesAnimatePending&) = delete;
+  LayerTreeHostProxyTestImplFrameCausesAnimatePending& operator=(
+      const LayerTreeHostProxyTestImplFrameCausesAnimatePending&) = delete;
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
@@ -453,9 +471,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestImplFrameCausesAnimatePending);
 };
 
 SINGLE_THREAD_TEST_F(LayerTreeHostProxyTestImplFrameCausesAnimatePending);
@@ -466,6 +481,10 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestNeedsCommitFromImpl() = default;
+  LayerTreeHostProxyTestNeedsCommitFromImpl(
+      const LayerTreeHostProxyTestNeedsCommitFromImpl&) = delete;
+  LayerTreeHostProxyTestNeedsCommitFromImpl& operator=(
+      const LayerTreeHostProxyTestNeedsCommitFromImpl&) = delete;
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
@@ -500,9 +519,6 @@
   }
 
   void AfterTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestNeedsCommitFromImpl);
 };
 
 SINGLE_THREAD_TEST_F(LayerTreeHostProxyTestNeedsCommitFromImpl);
@@ -514,8 +530,13 @@
     : public LayerTreeHostProxyTest {
  protected:
   LayerTreeHostProxyTestDelayedCommitDueToVisibility() = default;
+  LayerTreeHostProxyTestDelayedCommitDueToVisibility(
+      const LayerTreeHostProxyTestDelayedCommitDueToVisibility&) = delete;
   ~LayerTreeHostProxyTestDelayedCommitDueToVisibility() override = default;
 
+  LayerTreeHostProxyTestDelayedCommitDueToVisibility& operator=(
+      const LayerTreeHostProxyTestDelayedCommitDueToVisibility&) = delete;
+
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   void WillSendBeginMainFrameOnThread(LayerTreeHostImpl*) override {
@@ -537,8 +558,6 @@
 
  private:
   bool set_invisible_once_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestDelayedCommitDueToVisibility);
 };
 
 SINGLE_AND_MULTI_THREAD_TEST_F(
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index a42e2153..b6f7921 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/containers/flat_set.h"
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "cc/base/synced_property.h"
@@ -99,8 +98,11 @@
                 scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
                 scoped_refptr<SyncedBrowserControls> top_controls_shown_ratio,
                 scoped_refptr<SyncedElasticOverscroll> elastic_overscroll);
+  LayerTreeImpl(const LayerTreeImpl&) = delete;
   virtual ~LayerTreeImpl();
 
+  LayerTreeImpl& operator=(const LayerTreeImpl&) = delete;
+
   void Shutdown();
   void ReleaseResources();
   void OnPurgeMemory();
@@ -803,8 +805,6 @@
   LayerTreeLifecycle lifecycle_;
 
   std::vector<LayerTreeHost::PresentationTimeCallback> presentation_callbacks_;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeImpl);
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index 5c8054c..c752ebca 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "cc/trees/layer_tree_impl.h"
 
-#include "base/macros.h"
 #include "cc/layers/heads_up_display_layer_impl.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
 #include "cc/test/geometry_test_utils.h"
diff --git a/cc/trees/layer_tree_mutator.h b/cc/trees/layer_tree_mutator.h
index a25f40c..58e8aa4 100644
--- a/cc/trees/layer_tree_mutator.h
+++ b/cc/trees/layer_tree_mutator.h
@@ -79,20 +79,25 @@
   std::vector<WorkletAnimationId> peeked_animations;
 
   AnimationWorkletInput();
+  AnimationWorkletInput(const AnimationWorkletInput&) = delete;
   ~AnimationWorkletInput();
 
+  AnimationWorkletInput& operator=(const AnimationWorkletInput&) = delete;
+
 #if DCHECK_IS_ON()
   // Verifies all animation states have the expected worklet id.
   bool ValidateId(int worklet_id) const;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(AnimationWorkletInput);
 };
 
 class CC_EXPORT MutatorInputState {
  public:
   MutatorInputState();
+  MutatorInputState(const MutatorInputState&) = delete;
   ~MutatorInputState();
 
+  MutatorInputState& operator=(const MutatorInputState&) = delete;
+
   bool IsEmpty() const;
   void Add(AnimationWorkletInput::AddAndUpdateState&& state);
   void Update(AnimationWorkletInput::UpdateState&& state);
@@ -119,8 +124,6 @@
   // Returns iterator pointing to the entry in |inputs_| map whose key is id. It
   // inserts a new entry if none exists.
   AnimationWorkletInput& EnsureWorkletEntry(int id);
-
-  DISALLOW_COPY_AND_ASSIGN(MutatorInputState);
 };
 
 struct CC_EXPORT AnimationWorkletOutput {
diff --git a/cc/trees/occlusion_tracker.h b/cc/trees/occlusion_tracker.h
index 0f360f39..09c7aec 100644
--- a/cc/trees/occlusion_tracker.h
+++ b/cc/trees/occlusion_tracker.h
@@ -7,7 +7,6 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/base/simple_enclosed_region.h"
 #include "cc/cc_export.h"
 #include "cc/layers/effect_tree_layer_list_iterator.h"
@@ -31,8 +30,11 @@
 class CC_EXPORT OcclusionTracker {
  public:
   explicit OcclusionTracker(const gfx::Rect& screen_space_clip_rect);
+  OcclusionTracker(const OcclusionTracker&) = delete;
   ~OcclusionTracker();
 
+  OcclusionTracker& operator=(const OcclusionTracker&) = delete;
+
   // Return an occlusion that retains the current state of the tracker
   // and can be used outside of a layer walk to check occlusion.
   Occlusion GetCurrentOcclusionForLayer(
@@ -102,8 +104,6 @@
 
   gfx::Rect screen_space_clip_rect_;
   gfx::Size minimum_tracking_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(OcclusionTracker);
 };
 
 }  // namespace cc
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index 672f1c3..0a49df13 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -46,11 +46,13 @@
 class ScopedCompletionEvent {
  public:
   explicit ScopedCompletionEvent(CompletionEvent* event) : event_(event) {}
+  ScopedCompletionEvent(const ScopedCompletionEvent&) = delete;
   ~ScopedCompletionEvent() { event_->Signal(); }
 
+  ScopedCompletionEvent& operator=(const ScopedCompletionEvent&) = delete;
+
  private:
   CompletionEvent* const event_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedCompletionEvent);
 };
 
 ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index 21090c9..1f6f4be 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "cc/base/completion_event.h"
 #include "cc/base/delayed_unique_notifier.h"
@@ -31,8 +30,11 @@
   ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
             LayerTreeHost* layer_tree_host,
             TaskRunnerProvider* task_runner_provider);
+  ProxyImpl(const ProxyImpl&) = delete;
   ~ProxyImpl() override;
 
+  ProxyImpl& operator=(const ProxyImpl&) = delete;
+
   void UpdateBrowserControlsStateOnImpl(BrowserControlsState constraints,
                                         BrowserControlsState current,
                                         bool animate);
@@ -184,8 +186,6 @@
   // A weak pointer to ProxyMain that is invalidated when LayerTreeFrameSink is
   // released.
   base::WeakPtr<ProxyMain> proxy_main_frame_sink_bound_weak_ptr_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProxyImpl);
 };
 
 }  // namespace cc
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index 468bad8..76ee5de 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -5,7 +5,6 @@
 #ifndef CC_TREES_PROXY_MAIN_H_
 #define CC_TREES_PROXY_MAIN_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/input/browser_controls_state.h"
 #include "cc/trees/proxy.h"
@@ -33,9 +32,11 @@
  public:
   ProxyMain(LayerTreeHost* layer_tree_host,
             TaskRunnerProvider* task_runner_provider);
-
+  ProxyMain(const ProxyMain&) = delete;
   ~ProxyMain() override;
 
+  ProxyMain& operator=(const ProxyMain&) = delete;
+
   // Commits between the main and impl threads are processed through a pipeline
   // with the following stages. For efficiency we can early out at any stage if
   // we decide that no further processing is necessary.
@@ -166,8 +167,6 @@
   base::WeakPtrFactory<ProxyMain> frame_sink_bound_weak_factory_;
 
   base::WeakPtrFactory<ProxyMain> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProxyMain);
 };
 
 }  // namespace cc
diff --git a/cc/trees/render_frame_metadata_observer.h b/cc/trees/render_frame_metadata_observer.h
index 13b0263..4b30e52 100644
--- a/cc/trees/render_frame_metadata_observer.h
+++ b/cc/trees/render_frame_metadata_observer.h
@@ -5,7 +5,6 @@
 #ifndef CC_TREES_RENDER_FRAME_METADATA_OBSERVER_H_
 #define CC_TREES_RENDER_FRAME_METADATA_OBSERVER_H_
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/trees/render_frame_metadata.h"
 
@@ -22,8 +21,12 @@
 class CC_EXPORT RenderFrameMetadataObserver {
  public:
   RenderFrameMetadataObserver() = default;
+  RenderFrameMetadataObserver(const RenderFrameMetadataObserver&) = delete;
   virtual ~RenderFrameMetadataObserver() = default;
 
+  RenderFrameMetadataObserver& operator=(const RenderFrameMetadataObserver&) =
+      delete;
+
   // Binds on the current thread. This should only be called from the compositor
   // thread.
   virtual void BindToCurrentThread() = 0;
@@ -34,9 +37,6 @@
       const RenderFrameMetadata& render_frame_metadata,
       viz::CompositorFrameMetadata* compositor_frame_metadata,
       bool force_send) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RenderFrameMetadataObserver);
 };
 
 }  // namespace cc
diff --git a/cc/trees/scoped_abort_remaining_swap_promises.h b/cc/trees/scoped_abort_remaining_swap_promises.h
index b6c1197..af9cd79 100644
--- a/cc/trees/scoped_abort_remaining_swap_promises.h
+++ b/cc/trees/scoped_abort_remaining_swap_promises.h
@@ -5,7 +5,6 @@
 #ifndef CC_TREES_SCOPED_ABORT_REMAINING_SWAP_PROMISES_H_
 #define CC_TREES_SCOPED_ABORT_REMAINING_SWAP_PROMISES_H_
 
-#include "base/macros.h"
 #include "cc/trees/swap_promise.h"
 #include "cc/trees/swap_promise_manager.h"
 
@@ -16,15 +15,18 @@
   explicit ScopedAbortRemainingSwapPromises(
       SwapPromiseManager* swap_promise_manager)
       : swap_promise_manager_(swap_promise_manager) {}
+  ScopedAbortRemainingSwapPromises(const ScopedAbortRemainingSwapPromises&) =
+      delete;
 
   ~ScopedAbortRemainingSwapPromises() {
     swap_promise_manager_->BreakSwapPromises(SwapPromise::COMMIT_FAILS);
   }
 
+  ScopedAbortRemainingSwapPromises& operator=(
+      const ScopedAbortRemainingSwapPromises&) = delete;
+
  private:
   SwapPromiseManager* swap_promise_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAbortRemainingSwapPromises);
 };
 
 }  // namespace cc
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 107f91b2..e0f07ef9 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -8,7 +8,6 @@
 #include <limits>
 
 #include "base/cancelable_callback.h"
-#include "base/macros.h"
 #include "base/time/time.h"
 #include "cc/scheduler/scheduler.h"
 #include "cc/trees/layer_tree_host_impl.h"
@@ -35,8 +34,11 @@
       LayerTreeHost* layer_tree_host,
       LayerTreeHostSingleThreadClient* client,
       TaskRunnerProvider* task_runner_provider);
+  SingleThreadProxy(const SingleThreadProxy&) = delete;
   ~SingleThreadProxy() override;
 
+  SingleThreadProxy& operator=(const SingleThreadProxy&) = delete;
+
   // Proxy implementation
   bool IsStarted() const override;
   bool CommitToActiveTree() const override;
@@ -211,8 +213,6 @@
   base::WeakPtrFactory<SingleThreadProxy> frame_sink_bound_weak_factory_;
 
   base::WeakPtrFactory<SingleThreadProxy> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SingleThreadProxy);
 };
 
 // For use in the single-threaded case. In debug builds, it pretends that the
@@ -229,19 +229,22 @@
   explicit DebugScopedSetImplThread(TaskRunnerProvider* task_runner_provider) {}
 #endif
 
+  DebugScopedSetImplThread(const DebugScopedSetImplThread&) = delete;
+
   ~DebugScopedSetImplThread() {
 #if DCHECK_IS_ON()
     task_runner_provider_->SetCurrentThreadIsImplThread(previous_value_);
 #endif
   }
 
- private:
+  DebugScopedSetImplThread& operator=(const DebugScopedSetImplThread&) = delete;
+
 #if DCHECK_IS_ON()
+
+ private:
   bool previous_value_;
   TaskRunnerProvider* task_runner_provider_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(DebugScopedSetImplThread);
 };
 
 // For use in the single-threaded case. In debug builds, it pretends that the
@@ -258,19 +261,22 @@
   explicit DebugScopedSetMainThread(TaskRunnerProvider* task_runner_provider) {}
 #endif
 
+  DebugScopedSetMainThread(const DebugScopedSetMainThread&) = delete;
+
   ~DebugScopedSetMainThread() {
 #if DCHECK_IS_ON()
     task_runner_provider_->SetCurrentThreadIsImplThread(previous_value_);
 #endif
   }
 
- private:
+  DebugScopedSetMainThread& operator=(const DebugScopedSetMainThread&) = delete;
+
 #if DCHECK_IS_ON()
+
+ private:
   bool previous_value_;
   TaskRunnerProvider* task_runner_provider_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(DebugScopedSetMainThread);
 };
 
 // For use in the single-threaded case. In debug builds, it pretends that the
@@ -282,12 +288,14 @@
       TaskRunnerProvider* task_runner_provider)
       : impl_thread_(task_runner_provider),
         main_thread_blocked_(task_runner_provider) {}
+  DebugScopedSetImplThreadAndMainThreadBlocked(
+      const DebugScopedSetImplThreadAndMainThreadBlocked&) = delete;
+  DebugScopedSetImplThreadAndMainThreadBlocked& operator=(
+      const DebugScopedSetImplThreadAndMainThreadBlocked&) = delete;
 
  private:
   DebugScopedSetImplThread impl_thread_;
   DebugScopedSetMainThreadBlocked main_thread_blocked_;
-
-  DISALLOW_COPY_AND_ASSIGN(DebugScopedSetImplThreadAndMainThreadBlocked);
 };
 
 }  // namespace cc
diff --git a/cc/trees/swap_promise_manager.h b/cc/trees/swap_promise_manager.h
index da72a8ac..f2dc6e4 100644
--- a/cc/trees/swap_promise_manager.h
+++ b/cc/trees/swap_promise_manager.h
@@ -8,7 +8,6 @@
 #include <set>
 #include <vector>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/trees/swap_promise.h"
 
@@ -19,8 +18,11 @@
 class CC_EXPORT SwapPromiseManager {
  public:
   SwapPromiseManager();
+  SwapPromiseManager(const SwapPromiseManager&) = delete;
   ~SwapPromiseManager();
 
+  SwapPromiseManager& operator=(const SwapPromiseManager&) = delete;
+
   // Call this function when you expect there to be a swap buffer.
   // See swap_promise.h for how to use SwapPromise.
   void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise);
@@ -49,8 +51,6 @@
  private:
   std::vector<std::unique_ptr<SwapPromise>> swap_promise_list_;
   std::set<SwapPromiseMonitor*> swap_promise_monitors_;
-
-  DISALLOW_COPY_AND_ASSIGN(SwapPromiseManager);
 };
 
 }  // namespace cc
diff --git a/cc/trees/task_runner_provider.h b/cc/trees/task_runner_provider.h
index 42b0ed80..0bc19d3 100644
--- a/cc/trees/task_runner_provider.h
+++ b/cc/trees/task_runner_provider.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
@@ -35,6 +34,9 @@
         new TaskRunnerProvider(main_task_runner, impl_task_runner));
   }
 
+  TaskRunnerProvider(const TaskRunnerProvider&) = delete;
+  TaskRunnerProvider& operator=(const TaskRunnerProvider&) = delete;
+
   // TODO(vmpstr): Should these return scoped_refptr to task runners? Many
   // places turn them into scoped_refptrs. How many of them need to?
   base::SingleThreadTaskRunner* MainThreadTaskRunner() const;
@@ -70,8 +72,6 @@
   bool impl_thread_is_overridden_;
   bool is_main_thread_blocked_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(TaskRunnerProvider);
 };
 
 #if DCHECK_IS_ON()
@@ -83,24 +83,30 @@
     DCHECK(!task_runner_provider_->IsMainThreadBlocked());
     task_runner_provider_->SetMainThreadBlocked(true);
   }
+  DebugScopedSetMainThreadBlocked(const DebugScopedSetMainThreadBlocked&) =
+      delete;
   ~DebugScopedSetMainThreadBlocked() {
     DCHECK(task_runner_provider_->IsMainThreadBlocked());
     task_runner_provider_->SetMainThreadBlocked(false);
   }
 
+  DebugScopedSetMainThreadBlocked& operator=(
+      const DebugScopedSetMainThreadBlocked&) = delete;
+
  private:
   TaskRunnerProvider* task_runner_provider_;
-  DISALLOW_COPY_AND_ASSIGN(DebugScopedSetMainThreadBlocked);
 };
 #else
 class DebugScopedSetMainThreadBlocked {
  public:
   explicit DebugScopedSetMainThreadBlocked(
       TaskRunnerProvider* task_runner_provider) {}
+  DebugScopedSetMainThreadBlocked(const DebugScopedSetMainThreadBlocked&) =
+      delete;
   ~DebugScopedSetMainThreadBlocked() {}
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(DebugScopedSetMainThreadBlocked);
+  DebugScopedSetMainThreadBlocked& operator=(
+      const DebugScopedSetMainThreadBlocked&) = delete;
 };
 #endif
 
diff --git a/cc/trees/tree_synchronizer.h b/cc/trees/tree_synchronizer.h
index 1f0a1a1..81f1986 100644
--- a/cc/trees/tree_synchronizer.h
+++ b/cc/trees/tree_synchronizer.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "cc/cc_export.h"
 
 namespace cc {
@@ -19,6 +18,9 @@
 
 class CC_EXPORT TreeSynchronizer {
  public:
+  // Not instantiable.
+  TreeSynchronizer() = delete;
+
   // Accepts a Layer tree and returns a reference to a LayerImpl tree that
   // duplicates the structure of the Layer tree, reusing the LayerImpls in the
   // tree provided by old_layer_impl_root if possible.
@@ -30,11 +32,6 @@
                                   LayerTreeImpl* active_tree);
   static void PushLayerProperties(LayerTreeHost* host_tree,
                                   LayerTreeImpl* impl_tree);
-
- private:
-  TreeSynchronizer();  // Not instantiable.
-
-  DISALLOW_COPY_AND_ASSIGN(TreeSynchronizer);
 };
 
 }  // namespace cc
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index ae5d423..ae6b1d8 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -118,10 +118,10 @@
     "//components/strings:components_strings_grd",
     "//content/public/android:content_java_resources",
     "//third_party/android_data_chart:android_data_chart_java_resources",
-    "//third_party/android_deps:android_support_design_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_gridlayout_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_design_java",
+    "//third_party/android_deps:com_android_support_gridlayout_v7_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
   ]
   custom_package = "org.chromium.chrome"
 }
@@ -331,14 +331,14 @@
     "//third_party/android_data_chart:android_data_chart_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
     "//third_party/android_deps:android_arch_lifecycle_runtime_java",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_compat_java",
-    "//third_party/android_deps:android_support_design_java",
-    "//third_party/android_deps:android_support_v13_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_gridlayout_java",
-    "//third_party/android_deps:android_support_v7_mediarouter_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_design_java",
+    "//third_party/android_deps:com_android_support_gridlayout_v7_java",
+    "//third_party/android_deps:com_android_support_mediarouter_v7_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_v13_java",
     "//third_party/android_deps:com_google_dagger_dagger_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_lite_java",
     "//third_party/android_deps:javax_inject_javax_inject_java",
@@ -616,10 +616,10 @@
     "//net/android:net_java",
     "//services/media_session/public/cpp/android:media_session_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
-    "//third_party/android_deps:android_support_annotations_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_mediarouter_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_mediarouter_v7_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/blink/public:android_mojo_bindings_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
@@ -756,10 +756,10 @@
     "//services/service_manager/public/java:service_manager_java",
     "//third_party/android_data_chart:android_data_chart_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_design_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_design_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:com_google_ar_core_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_lite_java",
     "//third_party/android_support_test_runner:rules_java",
@@ -850,9 +850,9 @@
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
     "//third_party/custom_tabs_client:custom_tabs_support_java",
     "//third_party/junit",
     "//third_party/ub-uiautomator:ub_uiautomator_java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index d4c02f3..bac2bd62 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -13,7 +13,7 @@
     "//chrome/android:chrome_java",
     "//components/url_formatter/android:url_formatter_java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:android_support_design_java",
+    "//third_party/android_deps:com_android_support_design_java",
     "//third_party/android_deps:com_android_support_recyclerview_v7_java",
     "//third_party/android_deps:com_android_support_support_compat_java",
     "//third_party/android_deps:com_android_support_support_core_ui_java",
diff --git a/chrome/android/features/media_router/BUILD.gn b/chrome/android/features/media_router/BUILD.gn
index 66d317f..ed861e05 100644
--- a/chrome/android/features/media_router/BUILD.gn
+++ b/chrome/android/features/media_router/BUILD.gn
@@ -16,9 +16,9 @@
     "//base:base_java",
     "//chrome/android:chrome_java",
     "//services/media_session/public/cpp/android:media_session_java",
-    "//third_party/android_deps:android_support_compat_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_mediarouter_java",
+    "//third_party/android_deps:com_android_support_mediarouter_v7_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
     "//third_party/android_media:android_media_java",
   ]
   java_files = [
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 78854a9..13529d7 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -48,11 +48,11 @@
     "//content/public/android:content_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
     "//third_party/android_deps:android_arch_lifecycle_runtime_java",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_compat_java",
-    "//third_party/android_deps:android_support_v13_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_v13_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
     "//ui/android:ui_java",
   ]
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java
index b532812..2004074 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java
@@ -5,11 +5,14 @@
 package org.chromium.chrome.browser.tasks.tab_management;
 
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
 
 /**
- * Interface for the Tab Groups related UI.
+ * Interface for the Tab Groups related UI. This UI manages its own visibility through {@link
+ * BottomControlsCoordinator.BottomControlsVisibilityController}.
  */
 public interface TabGroupUi {
-    void initializeWithNative(ChromeActivity activity);
+    void initializeWithNative(ChromeActivity activity,
+            BottomControlsCoordinator.BottomControlsVisibilityController visibilityController);
     void destroy();
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
index 8ab604b..aec8f45 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -8,10 +8,12 @@
 import android.view.ViewGroup;
 
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.util.List;
@@ -45,7 +47,10 @@
      * Handle any initialization that occurs once native has been loaded.
      */
     @Override
-    public void initializeWithNative(ChromeActivity activity) {
+    public void initializeWithNative(ChromeActivity activity,
+            BottomControlsCoordinator.BottomControlsVisibilityController visibilityController) {
+        assert activity instanceof ChromeTabbedActivity;
+
         TabModelSelector tabModelSelector = activity.getTabModelSelector();
         TabContentManager tabContentManager = activity.getTabContentManager();
         mTabStripCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.STRIP,
@@ -55,7 +60,9 @@
         mTabGridSheetCoordinator = new TabGridSheetCoordinator(mContext,
                 activity.getBottomSheetController(), tabModelSelector, tabContentManager, activity);
 
-        mMediator = new TabGroupUiMediator(this, mTabStripToolbarModel, tabModelSelector, activity);
+        mMediator = new TabGroupUiMediator(visibilityController, this, mTabStripToolbarModel,
+                tabModelSelector, activity,
+                ((ChromeTabbedActivity) activity).getOverviewModeBehavior());
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 05cc81fb..9613412 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser.tasks.tab_management;
 
 import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
+import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
@@ -13,6 +15,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -50,28 +53,59 @@
     private final ResetHandler mResetHandler;
     private final TabModelSelector mTabModelSelector;
     private final TabCreatorManager mTabCreatorManager;
+    private final OverviewModeBehavior mOverviewModeBehavior;
+    private final OverviewModeBehavior.OverviewModeObserver mOverviewModeObserver;
+    private final BottomControlsCoordinator
+            .BottomControlsVisibilityController mVisibilityController;
 
-    TabGroupUiMediator(ResetHandler resetHandler, PropertyModel toolbarPropertyModel,
-            TabModelSelector tabModelSelector, TabCreatorManager tabCreatorManager) {
+    TabGroupUiMediator(
+            BottomControlsCoordinator.BottomControlsVisibilityController visibilityController,
+            ResetHandler resetHandler, PropertyModel toolbarPropertyModel,
+            TabModelSelector tabModelSelector, TabCreatorManager tabCreatorManager,
+            OverviewModeBehavior overviewModeBehavior) {
         mResetHandler = resetHandler;
         mToolbarPropertyModel = toolbarPropertyModel;
         mTabModelSelector = tabModelSelector;
         mTabCreatorManager = tabCreatorManager;
+        mOverviewModeBehavior = overviewModeBehavior;
+        mVisibilityController = visibilityController;
 
         // register for tab model
         mTabModelObserver = new EmptyTabModelObserver() {
             @Override
             public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
                 if (getRelatedTabsForId(lastId).contains(tab)) return;
-                mResetHandler.resetStripWithListOfTabs(getRelatedTabsForId(tab.getId()));
+                resetTabStripWithRelatedTabsForId(tab.getId());
+            }
+
+            @Override
+            public void didAddTab(Tab tab, int type) {
+                if (type == TabLaunchType.FROM_CHROME_UI) return;
+                resetTabStripWithRelatedTabsForId(tab.getId());
+            }
+        };
+        mOverviewModeObserver = new EmptyOverviewModeObserver() {
+            @Override
+            public void onOverviewModeStartedShowing(boolean showToolbar) {
+                resetTabStripWithRelatedTabsForId(Tab.INVALID_TAB_ID);
+            }
+
+            @Override
+            public void onOverviewModeFinishedHiding() {
+                Tab tab = mTabModelSelector.getCurrentTab();
+                if (tab == null) return;
+                resetTabStripWithRelatedTabsForId(tab.getId());
             }
         };
 
         mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(mTabModelObserver);
+        mOverviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver);
         setupToolbarClickHandlers();
         mToolbarPropertyModel.set(TabStripToolbarViewProperties.IS_MAIN_CONTENT_VISIBLE, true);
-        mResetHandler.resetStripWithListOfTabs(
-                getRelatedTabsForId(tabModelSelector.getCurrentTab().getId()));
+        Tab tab = mTabModelSelector.getCurrentTab();
+        if (tab != null) {
+            resetTabStripWithRelatedTabsForId(tab.getId());
+        }
     }
 
     private void setupToolbarClickHandlers() {
@@ -88,6 +122,20 @@
         });
     }
 
+    private void resetTabStripWithRelatedTabsForId(int id) {
+        List<Tab> listOfTabs = mTabModelSelector.getTabModelFilterProvider()
+                                       .getCurrentTabModelFilter()
+                                       .getRelatedTabList(id);
+
+        if (listOfTabs == null || listOfTabs.size() < 2) {
+            mResetHandler.resetStripWithListOfTabs(null);
+            mVisibilityController.setBottomControlsVisible(false);
+        } else {
+            mResetHandler.resetStripWithListOfTabs(listOfTabs);
+            mVisibilityController.setBottomControlsVisible(true);
+        }
+    }
+
     private List<Tab> getRelatedTabsForId(int id) {
         return mTabModelSelector.getTabModelFilterProvider()
                 .getCurrentTabModelFilter()
@@ -100,5 +148,6 @@
             mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
                     mTabModelObserver);
         }
+        mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver);
     }
 }
diff --git a/chrome/android/features/vr/BUILD.gn b/chrome/android/features/vr/BUILD.gn
index 917275c..57b5e54c 100644
--- a/chrome/android/features/vr/BUILD.gn
+++ b/chrome/android/features/vr/BUILD.gn
@@ -112,7 +112,7 @@
     "//content/public/android:content_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
     "//third_party/android_deps:android_arch_lifecycle_runtime_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
     "//third_party/gvr-android-keyboard:kb_java",
     "//ui/android:ui_full_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 4343ac1..b10330c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1213,7 +1213,8 @@
     public void onOrientationChange() {
         if (mActionModeController != null) mActionModeController.showControlsOnOrientationChange();
 
-        if (mBottomControlsCoordinator != null && FeatureUtilities.isAdaptiveToolbarEnabled()) {
+        if (mBottomControlsCoordinator != null && FeatureUtilities.isBottomToolbarEnabled()
+                && FeatureUtilities.isAdaptiveToolbarEnabled()) {
             mIsBottomToolbarVisible = mActivity.getResources().getConfiguration().orientation
                     != Configuration.ORIENTATION_LANDSCAPE;
             mToolbar.onBottomToolbarVisibilityChanged(mIsBottomToolbarVisible);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
index 054838a1..69ece79 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
@@ -38,6 +38,13 @@
  * controls offset is 0.
  */
 public class BottomControlsCoordinator {
+    /**
+     * Interface for the BottomControls component to hide and show itself.
+     */
+    public interface BottomControlsVisibilityController {
+        void setBottomControlsVisible(boolean isVisible);
+    }
+
     /** The mediator that handles events from outside the bottom controls. */
     private final BottomControlsMediator mMediator;
 
@@ -121,8 +128,7 @@
         }
 
         if (mTabGroupUi != null) {
-            mTabGroupUi.initializeWithNative(chromeActivity);
-            mMediator.setBottomControlsVisible(true);
+            mTabGroupUi.initializeWithNative(chromeActivity, mMediator::setBottomControlsVisible);
         }
     }
 
@@ -130,9 +136,6 @@
      * @param isVisible Whether the bottom control is visible.
      */
     public void setBottomControlsVisible(boolean isVisible) {
-        // TabGroupUi manages its own visibility
-        if (mTabGroupUi != null) return;
-
         mMediator.setBottomControlsVisible(isVisible);
         if (mBottomToolbarCoordinator != null) {
             mBottomToolbarCoordinator.setBottomToolbarVisible(isVisible);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
index b4a046b..7160a2a5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -18,6 +18,7 @@
 import android.os.Bundle;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -529,6 +530,7 @@
      * Test that the pending update file is deleted after update completes regardless of whether
      * update succeeded.
      */
+    @Ignore("https://crbug.com/937109")
     @Test
     public void testPendingUpdateFileDeletedAfterUpdateCompletion() throws Exception {
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
@@ -554,6 +556,7 @@
      * {@link WebApkUpdateManager#nativeStoreWebApkUpdateRequestToFile} creates the pending update
      * file but fails.
      */
+    @Ignore("https://crbug.com/937109")
     @Test
     public void testFileDeletedIfStoreWebApkUpdateRequestToFileFails() throws Exception {
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
diff --git a/chrome/android/webapk/libs/client/BUILD.gn b/chrome/android/webapk/libs/client/BUILD.gn
index 92169504..84fb107 100644
--- a/chrome/android/webapk/libs/client/BUILD.gn
+++ b/chrome/android/webapk/libs/client/BUILD.gn
@@ -19,7 +19,7 @@
     "//base:base_java",
     "//chrome/android/webapk/libs/common:common_java",
     "//chrome/android/webapk/libs/runtime_library:webapk_service_aidl_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   srcjar_deps = [ ":runtime_library_version_java" ]
 }
diff --git a/chrome/android/webapk/libs/common/BUILD.gn b/chrome/android/webapk/libs/common/BUILD.gn
index 527f068..da53ae3 100644
--- a/chrome/android/webapk/libs/common/BUILD.gn
+++ b/chrome/android/webapk/libs/common/BUILD.gn
@@ -18,7 +18,7 @@
   java_files = [ "src/org/chromium/webapk/lib/common/splash/SplashLayout.java" ]
   deps = [
     ":splash_resources",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
 }
 
diff --git a/chrome/android/webapk/libs/runtime_library/BUILD.gn b/chrome/android/webapk/libs/runtime_library/BUILD.gn
index 477d5f7..eef3a89 100644
--- a/chrome/android/webapk/libs/runtime_library/BUILD.gn
+++ b/chrome/android/webapk/libs/runtime_library/BUILD.gn
@@ -35,7 +35,7 @@
       [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ]
   srcjar_deps = [ ":webapk_service_aidl" ]
   deps = [
-    "//third_party/android_deps:android_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
   ]
 }
 
@@ -45,7 +45,7 @@
       [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ]
   deps = [
     ":webapk_service_aidl_java",
-    "//third_party/android_deps:android_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
   ]
 }
 
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 028f65d..d7b200ec 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1648,9 +1648,12 @@
   <message name="IDS_TERMS_OF_SERVICE_SCREEN_ACCEPT_BUTTON" desc="Text of the accept button on the Terms of Service screen.">
     Accept and continue
   </message>
-  <message name="IDS_CONTROLLED_SETTING_OWNER" desc="Text displayed in the controlled settings bubble when a setting's value can be edited only by the owner.">
+  <message name="IDS_CONTROLLED_SETTING_WITH_OWNER" desc="Text displayed in the controlled settings bubble when a setting's value can be edited only by the owner.">
     This setting is managed by the device owner, <ph name="OWNER_EMAIL">$1<ex>john@google.com</ex></ph>.
   </message>
+  <message name="IDS_CONTROLLED_SETTING_NO_OWNER" desc="Text displayed in the controlled settings bubble when a setting's value can be edited only by the owner.">
+    This setting is managed by the device owner.
+  </message>
   <message name="IDS_CONTROLLED_SETTING_SHARED" desc="Text displayed in the controlled settings bubble when a setting's value belongs to the primary user but can be edited.">
     This setting belongs to <ph name="OWNER_EMAIL">$1<ex>john@google.com</ex></ph>.
   </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 3d5a59e3..915a5eb 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -875,8 +875,6 @@
     "net/proxy_config_monitor.h",
     "net/proxy_service_factory.cc",
     "net/proxy_service_factory.h",
-    "net/quota_policy_channel_id_store.cc",
-    "net/quota_policy_channel_id_store.h",
     "net/referrer.cc",
     "net/referrer.h",
     "net/reporting_permissions_checker.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a350f6e..1d70726b 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -194,6 +194,10 @@
 #include "chrome/browser/win/titlebar_config.h"
 #endif  // OS_WIN
 
+#if defined(TOOLKIT_VIEWS)
+#include "ui/views/animation/installable_ink_drop.h"
+#endif  // defined(TOOLKIT_VIEWS)
+
 using flags_ui::FeatureEntry;
 using flags_ui::kOsAndroid;
 using flags_ui::kOsCrOS;
@@ -2914,9 +2918,6 @@
      flag_descriptions::kEnableFullscreenHandwritingVirtualKeyboardDescription,
      kOsCrOS,
      FEATURE_VALUE_TYPE(features::kEnableFullscreenHandwritingVirtualKeyboard)},
-    {"enable-per-user-timezone", flag_descriptions::kEnablePerUserTimezoneName,
-     flag_descriptions::kEnablePerUserTimezoneDescription, kOsCrOS,
-     SINGLE_DISABLE_VALUE_TYPE(chromeos::switches::kDisablePerUserTimezone)},
     {"enable-virtual-keyboard-ukm",
      flag_descriptions::kEnableVirtualKeyboardUkmName,
      flag_descriptions::kEnableVirtualKeyboardUkmDescription, kOsCrOS,
@@ -3487,8 +3488,9 @@
     {"unsafely-treat-insecure-origin-as-secure",
      flag_descriptions::kTreatInsecureOriginAsSecureName,
      flag_descriptions::kTreatInsecureOriginAsSecureDescription, kOsAll,
-     ORIGIN_LIST_VALUE_TYPE(switches::kUnsafelyTreatInsecureOriginAsSecure,
-                            "")},
+     ORIGIN_LIST_VALUE_TYPE(
+         network::switches::kUnsafelyTreatInsecureOriginAsSecure,
+         "")},
 
 #if defined(OS_CHROMEOS)
     {"enable-app-shortcut-search",
@@ -4082,6 +4084,12 @@
      FEATURE_VALUE_TYPE(features::kIntentPicker)},
 #endif  // !defined(OS_ANDROID)
 
+#if defined(TOOLKIT_VIEWS)
+    {"installable-ink-drop", flag_descriptions::kInstallableInkDropName,
+     flag_descriptions::kInstallableInkDropDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(views::kInstallableInkDropFeature)},
+#endif  // defined(TOOLKIT_VIEWS)
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/background_sync_launcher_android.cc b/chrome/browser/android/background_sync_launcher_android.cc
index 8eaedf25..effc509 100644
--- a/chrome/browser/android/background_sync_launcher_android.cc
+++ b/chrome/browser/android/background_sync_launcher_android.cc
@@ -8,6 +8,7 @@
 
 #include "base/android/callback_android.h"
 #include "base/barrier_closure.h"
+#include "base/bind.h"
 #include "base/feature_list.h"
 #include "chrome/browser/android/chrome_feature_list.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -52,12 +53,10 @@
 }
 
 // static
-void BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped(
-    bool launch_when_next_online,
-    int64_t min_delay_ms) {
+void BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  Get()->LaunchBrowserIfStoppedImpl(launch_when_next_online, min_delay_ms);
+  Get()->LaunchBrowserIfStoppedImpl();
 }
 
 // static
@@ -76,24 +75,38 @@
       base::android::AttachCurrentThread());
 }
 
-void BackgroundSyncLauncherAndroid::LaunchBrowserIfStoppedImpl(
-    bool launch_when_next_online,
-    int64_t min_delay_ms) {
+void BackgroundSyncLauncherAndroid::LaunchBrowserIfStoppedImpl() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
+  auto* profile = ProfileManager::GetLastUsedProfile();
+  DCHECK(profile);
+
+  auto* storage_partition =
+      content::BrowserContext::GetDefaultStoragePartition(profile);
+  storage_partition->GetBackgroundSyncContext()
+      ->GetSoonestWakeupDeltaAcrossPartitions(
+          profile,
+          base::BindOnce(
+              &BackgroundSyncLauncherAndroid::LaunchBrowserWithWakeupDelta,
+              base::Unretained(this)));
+}
+
+void BackgroundSyncLauncherAndroid::LaunchBrowserWithWakeupDelta(
+    base::TimeDelta soonest_wakeup_delta) {
   JNIEnv* env = base::android::AttachCurrentThread();
+  int64_t min_delay_ms = soonest_wakeup_delta.InMilliseconds();
 
   if (!base::FeatureList::IsEnabled(
           chrome::android::kBackgroundTaskSchedulerForBackgroundSync)) {
     Java_BackgroundSyncLauncher_launchBrowserIfStopped(
-        env, java_gcm_network_manager_launcher_, launch_when_next_online,
+        env, java_gcm_network_manager_launcher_, soonest_wakeup_delta.is_max(),
         min_delay_ms);
     return;
   }
 
   Java_BackgroundSyncBackgroundTaskScheduler_launchBrowserIfStopped(
       env, java_background_sync_background_task_scheduler_launcher_,
-      launch_when_next_online, min_delay_ms);
+      soonest_wakeup_delta.is_max(), min_delay_ms);
 }
 
 void BackgroundSyncLauncherAndroid::FireBackgroundSyncEvents(
@@ -103,51 +116,12 @@
   auto* profile = ProfileManager::GetLastUsedProfile();
   DCHECK(profile);
 
-  int num_partitions = 0;
-  content::BrowserContext::ForEachStoragePartition(
-      profile, base::BindRepeating(
-                   [](int* num_partitions,
-                      content::StoragePartition* storage_partition) {
-                     (*num_partitions)++;
-                   },
-                   &num_partitions));
-
-  // This class is a singleton, which is only destructed on program exit.
-  // Therefore, use of base::Unretained(this) is safe.
-  base::RepeatingClosure done_closure = base::BarrierClosure(
-      num_partitions,
-      base::BindOnce(base::android::RunRunnableAndroid,
-                     base::android::ScopedJavaGlobalRef<jobject>(j_runnable)));
-
-  content::BrowserContext::ForEachStoragePartition(
-      profile,
-      base::BindRepeating(&BackgroundSyncLauncherAndroid::
-                              FireBackgroundSyncEventsForStoragePartition,
-                          base::Unretained(this), done_closure));
+  auto* storage_partition =
+      content::BrowserContext::GetDefaultStoragePartition(profile);
+  storage_partition->GetBackgroundSyncContext()
+      ->FireBackgroundSyncEventsAcrossPartitions(profile, j_runnable);
 }
 
-void BackgroundSyncLauncherAndroid::FireBackgroundSyncEventsForStoragePartition(
-    base::OnceClosure done_closure,
-    content::StoragePartition* storage_partition) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  content::BackgroundSyncContext* sync_context =
-      storage_partition->GetBackgroundSyncContext();
-  if (!sync_context) {
-    std::move(done_closure).Run();
-    return;
-  }
-
-  sync_context->FireBackgroundSyncEventsForStoragePartition(
-      storage_partition, std::move(done_closure));
-}
-
-void BackgroundSyncLauncherAndroid::OnFiredBackgroundSyncEvents(
-    base::android::ScopedJavaGlobalRef<jobject> j_runnable) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  base::android::RunRunnableAndroid(j_runnable);
-}
 
 BackgroundSyncLauncherAndroid::BackgroundSyncLauncherAndroid() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/android/background_sync_launcher_android.h b/chrome/browser/android/background_sync_launcher_android.h
index 1afb9bae..25cfec2 100644
--- a/chrome/browser/android/background_sync_launcher_android.h
+++ b/chrome/browser/android/background_sync_launcher_android.h
@@ -13,10 +13,7 @@
 #include "base/callback_forward.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-
-namespace content {
-class StoragePartition;
-}  // namespace content
+#include "base/time/time.h"
 
 // The BackgroundSyncLauncherAndroid singleton owns the Java
 // BackgroundSyncLauncher object and is used to register interest in starting
@@ -26,8 +23,12 @@
  public:
   static BackgroundSyncLauncherAndroid* Get();
 
-  static void LaunchBrowserIfStopped(bool launch_when_next_online,
-                                     int64_t min_delay_ms);
+  // Calculates the soonest wakeup time across all the storage
+  // partitions for the non-incognito profile and ensures that the browser
+  // is running when the device next goes online after that time has passed.
+  // If this time is set to base::TimeDelta::Max() across all storage
+  // partitions, the wake-up task is cancelled.
+  static void LaunchBrowserIfStopped();
 
   static bool ShouldDisableBackgroundSync();
 
@@ -47,13 +48,8 @@
   BackgroundSyncLauncherAndroid();
   ~BackgroundSyncLauncherAndroid();
 
-  void LaunchBrowserIfStoppedImpl(bool launch_when_next_online,
-                                  int64_t min_delay_ms);
-  void FireBackgroundSyncEventsForStoragePartition(
-      base::OnceClosure done_closure,
-      content::StoragePartition* storage_partition);
-  void OnFiredBackgroundSyncEvents(
-      base::android::ScopedJavaGlobalRef<jobject> j_runnable);
+  void LaunchBrowserIfStoppedImpl();
+  void LaunchBrowserWithWakeupDelta(base::TimeDelta soonest_wakeup_delta);
 
   base::android::ScopedJavaGlobalRef<jobject>
       java_gcm_network_manager_launcher_;
diff --git a/chrome/browser/background_sync/background_sync_controller_impl.cc b/chrome/browser/background_sync/background_sync_controller_impl.cc
index 40c86396..f73f95e2 100644
--- a/chrome/browser/background_sync/background_sync_controller_impl.cc
+++ b/chrome/browser/background_sync/background_sync_controller_impl.cc
@@ -114,17 +114,13 @@
                                           origin.GetURL());
 }
 
-void BackgroundSyncControllerImpl::RunInBackground(bool enabled,
-                                                   int64_t min_ms) {
+void BackgroundSyncControllerImpl::RunInBackground() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (profile_->IsOffTheRecord())
     return;
 #if defined(OS_ANDROID)
-  BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped(enabled, min_ms);
-#else
-// TODO(jkarlin): Use BackgroundModeManager to enter background mode. See
-// https://crbug.com/484201.
+  BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped();
 #endif
 }
 
diff --git a/chrome/browser/background_sync/background_sync_controller_impl.h b/chrome/browser/background_sync/background_sync_controller_impl.h
index 6446b77..e5739a39 100644
--- a/chrome/browser/background_sync/background_sync_controller_impl.h
+++ b/chrome/browser/background_sync/background_sync_controller_impl.h
@@ -45,7 +45,7 @@
   void GetParameterOverrides(
       content::BackgroundSyncParameters* parameters) const override;
   void NotifyBackgroundSyncRegistered(const url::Origin& origin) override;
-  void RunInBackground(bool enabled, int64_t min_ms) override;
+  void RunInBackground() override;
 
  protected:
   // Virtual for testing.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 48ef94d..bc8af9d 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -327,6 +327,7 @@
 #include "services/image_annotation/public/mojom/constants.mojom.h"
 #include "services/image_annotation/public/mojom/image_annotation.mojom.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/network_switches.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/preferences/public/cpp/in_process_service_factory.h"
 #include "services/preferences/public/mojom/preferences.mojom.h"
@@ -2106,7 +2107,7 @@
 
       if (prefs->HasPrefPath(prefs::kUnsafelyTreatInsecureOriginAsSecure)) {
         command_line->AppendSwitchASCII(
-            switches::kUnsafelyTreatInsecureOriginAsSecure,
+            network::switches::kUnsafelyTreatInsecureOriginAsSecure,
             prefs->GetString(prefs::kUnsafelyTreatInsecureOriginAsSecure));
       }
 
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 9fd16ba..5bf5279 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -57,9 +57,8 @@
 #include "chrome/grit/browser_resources.h"
 #include "chromeos/audio/chromeos_sounds.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager_client.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_member.h"
 #include "components/prefs/pref_service.h"
@@ -149,8 +148,7 @@
 // stop followed by start ensures we both stop a started job, and also start
 // brltty.
 void RestartBrltty(const std::string& address) {
-  chromeos::UpstartClient* client =
-      chromeos::DBusThreadManager::Get()->GetUpstartClient();
+  chromeos::UpstartClient* client = chromeos::UpstartClient::Get();
   client->StopJob(kBrlttyUpstartJobName, EmptyVoidDBusMethodCallback());
 
   std::vector<std::string> args;
@@ -1345,8 +1343,8 @@
 void AccessibilityManager::PostUnloadChromeVox() {
   // Do any teardown work needed immediately after ChromeVox actually unloads.
   // Stop brltty.
-  chromeos::DBusThreadManager::Get()->GetUpstartClient()->StopJob(
-      kBrlttyUpstartJobName, EmptyVoidDBusMethodCallback());
+  chromeos::UpstartClient::Get()->StopJob(kBrlttyUpstartJobName,
+                                          EmptyVoidDBusMethodCallback());
 
   PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS);
 
diff --git a/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc b/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc
index 42d55b0b..3609ba1 100644
--- a/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc
@@ -21,6 +21,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_session_runner.h"
 #include "components/arc/arc_util.h"
@@ -54,6 +55,7 @@
     chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
         std::make_unique<chromeos::FakeSessionManagerClient>());
     chromeos::DBusThreadManager::Initialize();
+    chromeos::UpstartClient::InitializeFake();
 
     SetArcAvailableCommandLineForTesting(
         base::CommandLine::ForCurrentProcess());
@@ -90,6 +92,7 @@
     arc_session_manager_.reset();
     identity_test_env_profile_adaptor_.reset();
     profile_.reset();
+    chromeos::UpstartClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
 
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
index d184c47..6f44589 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -43,6 +43,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/arc_features.h"
 #include "components/arc/arc_prefs.h"
@@ -181,6 +182,7 @@
         std::make_unique<chromeos::FakeSessionManagerClient>());
 
     chromeos::PowerManagerClient::Initialize();
+    chromeos::UpstartClient::InitializeFake();
 
     SetArcAvailableCommandLineForTesting(
         base::CommandLine::ForCurrentProcess());
@@ -208,6 +210,7 @@
     profile_.reset();
     arc_session_manager_.reset();
     arc_service_manager_.reset();
+    chromeos::UpstartClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
diff --git a/chrome/browser/chromeos/dbus/dbus_helper.cc b/chrome/browser/chromeos/dbus/dbus_helper.cc
index 94afeab7..c251cb4 100644
--- a/chrome/browser/chromeos/dbus/dbus_helper.cc
+++ b/chrome/browser/chromeos/dbus/dbus_helper.cc
@@ -10,6 +10,7 @@
 #include "chromeos/dbus/hammerd/hammerd_client.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "ui/base/ui_base_features.h"
 
@@ -33,6 +34,14 @@
   PowerManagerClient::Initialize(bus);
   SystemClockClient::Initialize(bus);
 
+  // TODO(stevenjb): Modify PowerManagerClient and SystemClockClient to use
+  // the same pattern as UpstartClient.
+  if (bus) {
+    UpstartClient::Initialize(bus);
+  } else {
+    UpstartClient::InitializeFake();
+  }
+
   // Initialize the device settings service so that we'll take actions per
   // signals sent from the session manager. This needs to happen before
   // g_browser_process initializes BrowserPolicyConnector.
@@ -41,6 +50,7 @@
 }
 
 void ShutdownDBus() {
+  UpstartClient::Shutdown();
   SystemClockClient::Shutdown();
   PowerManagerClient::Shutdown();
 
diff --git a/chrome/browser/chromeos/login/active_directory_test_helper.cc b/chrome/browser/chromeos/login/active_directory_test_helper.cc
index e7239c5..02c1839 100644
--- a/chrome/browser/chromeos/login/active_directory_test_helper.cc
+++ b/chrome/browser/chromeos/login/active_directory_test_helper.cc
@@ -16,7 +16,7 @@
 #include "chromeos/dbus/auth_policy_client.h"
 #include "chromeos/dbus/authpolicy/active_directory_info.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/dbus/util/tpm_util.h"
 #include "chromeos/login/auth/authpolicy_login_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -38,9 +38,7 @@
   ASSERT_EQ(2u, user_and_domain.size());
 
   // Start the D-Bus service.
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->StartAuthPolicyService();
+  chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
   // Join the AD domain.
   chromeos::AuthPolicyLoginHelper helper;
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
index be4ba4e..e98b2d4 100644
--- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -25,7 +25,7 @@
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_auth_policy_client.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 
@@ -511,9 +511,7 @@
       enrollment_screen(), kAdUserDomain, std::string(), kDMToken);
   SubmitEnrollmentCredentials();
 
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->StartAuthPolicyService();
+  chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
   CheckActiveDirectoryCredentialsShown();
   CheckConfigurationSelectionVisible(false);
@@ -545,9 +543,7 @@
 
   SubmitEnrollmentCredentials();
 
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->StartAuthPolicyService();
+  chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
   content::DOMMessageQueue message_queue;
   SetupActiveDirectoryJSNotifications();
@@ -582,9 +578,7 @@
       enrollment_screen(), kAdUserDomain, std::string(), kDMToken);
   SubmitEnrollmentCredentials();
 
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->StartAuthPolicyService();
+  chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
   content::DOMMessageQueue message_queue;
   // Checking error in case of empty password. Whether password is not empty
@@ -630,9 +624,7 @@
       enrollment_screen(), kAdUserDomain, std::string(), kDMToken);
   SubmitEnrollmentCredentials();
 
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->StartAuthPolicyService();
+  chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
   content::DOMMessageQueue message_queue;
   SetupActiveDirectoryJSNotifications();
@@ -657,9 +649,7 @@
       enrollment_screen(), kAdUserDomain, binary_config, kDMToken);
   SubmitEnrollmentCredentials();
 
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->StartAuthPolicyService();
+  chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
   ExecutePendingJavaScript();
   content::DOMMessageQueue message_queue;
diff --git a/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc b/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc
index 4785e65..65d2025 100644
--- a/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc
+++ b/chrome/browser/chromeos/login/screens/mock_welcome_screen.cc
@@ -7,10 +7,9 @@
 namespace chromeos {
 
 MockWelcomeScreen::MockWelcomeScreen(
-    Delegate* delegate,
     WelcomeView* view,
     const base::RepeatingClosure& exit_callback)
-    : WelcomeScreen(delegate, view, exit_callback) {}
+    : WelcomeScreen(view, exit_callback) {}
 
 void MockWelcomeScreen::ExitScreen() {
   exit_callback()->Run();
diff --git a/chrome/browser/chromeos/login/screens/mock_welcome_screen.h b/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
index 6d39c05..6436b25 100644
--- a/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
+++ b/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
@@ -16,8 +16,7 @@
 
 class MockWelcomeScreen : public WelcomeScreen {
  public:
-  MockWelcomeScreen(Delegate* delegate,
-                    WelcomeView* view,
+  MockWelcomeScreen(WelcomeView* view,
                     const base::RepeatingClosure& exit_callback);
   ~MockWelcomeScreen() override;
 
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.cc b/chrome/browser/chromeos/login/screens/welcome_screen.cc
index 6bcd29a..2309386 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.cc
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.cc
@@ -36,8 +36,6 @@
 namespace {
 
 constexpr char kUserActionContinueButtonClicked[] = "continue";
-constexpr char kUserActionConnectDebuggingFeaturesClicked[] =
-    "connect-debugging-features";
 
 }  // namespace
 
@@ -52,12 +50,10 @@
       manager->GetScreen(OobeScreen::SCREEN_OOBE_WELCOME));
 }
 
-WelcomeScreen::WelcomeScreen(Delegate* delegate,
-                             WelcomeView* view,
+WelcomeScreen::WelcomeScreen(WelcomeView* view,
                              const base::RepeatingClosure& exit_callback)
     : BaseScreen(OobeScreen::SCREEN_OOBE_WELCOME),
       view_(view),
-      delegate_(delegate),
       exit_callback_(exit_callback),
       weak_factory_(this) {
   if (view_)
@@ -205,9 +201,6 @@
 void WelcomeScreen::OnUserAction(const std::string& action_id) {
   if (action_id == kUserActionContinueButtonClicked) {
     OnContinueButtonPressed();
-  } else if (action_id == kUserActionConnectDebuggingFeaturesClicked) {
-    if (delegate_)
-      delegate_->OnEnableDebuggingScreenRequested();
   } else {
     BaseScreen::OnUserAction(action_id);
   }
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.h b/chrome/browser/chromeos/login/screens/welcome_screen.h
index 2842950..6eba275 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.h
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.h
@@ -31,14 +31,6 @@
 class WelcomeScreen : public BaseScreen,
                       public input_method::InputMethodManager::Observer {
  public:
-  class Delegate {
-   public:
-    virtual ~Delegate() {}
-
-    // Called when enable debugging screen is requested.
-    virtual void OnEnableDebuggingScreenRequested() = 0;
-  };
-
   class Observer {
    public:
     virtual ~Observer() {}
@@ -47,9 +39,7 @@
     virtual void OnLanguageListReloaded() = 0;
   };
 
-  WelcomeScreen(Delegate* delegate,
-                WelcomeView* view,
-                const base::RepeatingClosure& exit_callback);
+  WelcomeScreen(WelcomeView* view, const base::RepeatingClosure& exit_callback);
   ~WelcomeScreen() override;
 
   static WelcomeScreen* Get(ScreenManager* manager);
@@ -130,7 +120,6 @@
   std::unique_ptr<CrosSettings::ObserverSubscription> timezone_subscription_;
 
   WelcomeView* view_ = nullptr;
-  Delegate* delegate_ = nullptr;
   base::RepeatingClosure exit_callback_;
 
   std::string input_method_;
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
index aace7b26..d976d792 100644
--- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -76,7 +76,7 @@
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/proxy/proxy_config_service_impl.h"
 #include "chromeos/settings/cros_settings_names.h"
@@ -212,8 +212,8 @@
   const std::string board_name = board[0];
   if (board_name != "eve" && board_name != "nocturne")
     return;
-  chromeos::DBusThreadManager::Get()->GetUpstartClient()->StartJob(
-      kBluetoothLoggingUpstartJob, {}, EmptyVoidDBusMethodCallback());
+  chromeos::UpstartClient::Get()->StartJob(kBluetoothLoggingUpstartJob, {},
+                                           EmptyVoidDBusMethodCallback());
 }
 
 bool IsManagedSessionEnabled(policy::DeviceLocalAccountPolicyBroker* broker) {
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index ed4a9d56..d2bc4e9 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -69,6 +69,7 @@
 #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h"
 #include "chrome/browser/chromeos/login/screens/update_required_screen.h"
 #include "chrome/browser/chromeos/login/screens/update_screen.h"
+#include "chrome/browser/chromeos/login/screens/welcome_screen.h"
 #include "chrome/browser/chromeos/login/screens/welcome_view.h"
 #include "chrome/browser/chromeos/login/screens/wrong_hwid_screen.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
@@ -374,7 +375,7 @@
 
   if (screen == OobeScreen::SCREEN_OOBE_WELCOME) {
     return std::make_unique<WelcomeScreen>(
-        this, oobe_ui->GetWelcomeView(),
+        oobe_ui->GetWelcomeView(),
         base::BindRepeating(&WizardController::OnWelcomeScreenExit,
                             weak_factory_.GetWeakPtr()));
   } else if (screen == OobeScreen::SCREEN_OOBE_NETWORK) {
@@ -1552,11 +1553,6 @@
   SetCurrentScreen(parent_screen);
 }
 
-void WizardController::OnEnableDebuggingScreenRequested() {
-  if (!login_screen_started())
-    AdvanceToScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING);
-}
-
 void WizardController::OnAccessibilityStatusChanged(
     const AccessibilityStatusEventDetails& details) {
   enum AccessibilityNotificationType type = details.notification_type;
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 3d7693b6..8b06156 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -33,8 +33,8 @@
 #include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h"
 #include "chrome/browser/chromeos/login/screens/terms_of_service_screen.h"
 #include "chrome/browser/chromeos/login/screens/update_screen.h"
-#include "chrome/browser/chromeos/login/screens/welcome_screen.h"
 #include "chrome/browser/chromeos/policy/enrollment_config.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
 
 class PrefService;
 
@@ -55,8 +55,7 @@
 
 // Class that manages control flow between wizard screens. Wizard controller
 // interacts with screen controllers to move the user between screens.
-class WizardController : public BaseScreenDelegate,
-                         public WelcomeScreen::Delegate {
+class WizardController : public BaseScreenDelegate {
  public:
   WizardController();
   ~WizardController() override;
@@ -267,9 +266,6 @@
   void ShowErrorScreen() override;
   void HideErrorScreen(BaseScreen* parent_screen) override;
 
-  // Override from WelcomeScreen::Delegate:
-  void OnEnableDebuggingScreenRequested() override;
-
   void OnHIDScreenNecessityCheck(bool screen_needed);
 
   // Notification of a change in the state of an accessibility setting.
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 8ffa727..3000cc91 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -583,7 +583,7 @@
     // Set up the mocks for all screens.
     mock_welcome_screen_ =
         MockScreenExpectLifecycle(std::make_unique<MockWelcomeScreen>(
-            wizard_controller, GetOobeUI()->GetWelcomeView(),
+            GetOobeUI()->GetWelcomeView(),
             base::BindRepeating(&WizardController::OnWelcomeScreenExit,
                                 base::Unretained(wizard_controller))));
 
@@ -2286,11 +2286,16 @@
   EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
   EXPECT_CALL(*mock_enable_debugging_screen_, Show()).Times(1);
 
+  // Find the enable debugging link element (in the appropriate shadow root),
+  // and click it.
   ASSERT_TRUE(
-      JSExecute("chrome.send('login.WelcomeScreen.userActed', "
-                "['connect-debugging-features']);"));
+      JSExecute("(function() {"
+                "  var root = ['oobe-welcome-md', 'welcomeScreen'].reduce("
+                "    (root, id) => root.getElementById(id).shadowRoot,"
+                "    document);"
+                "  root.getElementById('enableDebuggingLink').click();"
+                "})();"));
 
-  // Let update screen smooth time process (time = 0ms).
   content::RunAllPendingInMessageLoop();
 
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING);
@@ -2744,7 +2749,7 @@
     ExpectBindUnbind(mock_welcome_view_.get());
     mock_welcome_screen_ =
         MockScreenExpectLifecycle(std::make_unique<MockWelcomeScreen>(
-            wizard_controller, mock_welcome_view_.get(),
+            mock_welcome_view_.get(),
             base::BindRepeating(&WizardController::OnWelcomeScreenExit,
                                 base::Unretained(wizard_controller))));
 
@@ -2844,7 +2849,7 @@
     mock_welcome_view_ = std::make_unique<MockWelcomeView>();
     mock_welcome_screen_ =
         MockScreenExpectLifecycle(std::make_unique<MockWelcomeScreen>(
-            wizard_controller, mock_welcome_view_.get(),
+            mock_welcome_view_.get(),
             base::BindRepeating(&WizardController::OnWelcomeScreenExit,
                                 base::Unretained(wizard_controller))));
   }
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
index 94776513d..a4eb63e 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -51,7 +51,7 @@
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/onc/onc_certificate_importer_impl.h"
@@ -117,9 +117,7 @@
             chromeos::InstallAttributes::Get(), GetBackgroundTaskRunner());
 
     if (chromeos::InstallAttributes::Get()->IsActiveDirectoryManaged()) {
-      chromeos::DBusThreadManager::Get()
-          ->GetUpstartClient()
-          ->StartAuthPolicyService();
+      chromeos::UpstartClient::Get()->StartAuthPolicyService();
 
       device_active_directory_policy_manager_ =
           new DeviceActiveDirectoryPolicyManager(
diff --git a/chrome/browser/chromeos/policy/device_account_initializer.cc b/chrome/browser/chromeos/policy/device_account_initializer.cc
index 980ec30..143bbd8 100644
--- a/chrome/browser/chromeos/policy/device_account_initializer.cc
+++ b/chrome/browser/chromeos/policy/device_account_initializer.cc
@@ -33,7 +33,6 @@
 #include "chromeos/dbus/auth_policy_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
 #include "components/policy/core/common/cloud/dm_auth.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "google_apis/gaia/gaia_auth_util.h"
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
index 639e1cb..40746bf 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -31,7 +31,7 @@
 #include "chromeos/dbus/auth_policy_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/policy/core/common/cloud/dm_auth.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "google_apis/gaia/gaia_auth_util.h"
@@ -351,9 +351,7 @@
         // Do nothing.
         break;
       case DEVICE_MODE_ENTERPRISE_AD:
-        chromeos::DBusThreadManager::Get()
-            ->GetUpstartClient()
-            ->StartAuthPolicyService();
+        chromeos::UpstartClient::Get()->StartAuthPolicyService();
         break;
       default:
         LOG(ERROR) << "Supplied device mode is not supported:" << device_mode_;
diff --git a/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.cc b/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.cc
index f66db98..d68d01c 100644
--- a/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.cc
+++ b/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.h"
+#include "chromeos/constants/chromeos_pref_names.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
@@ -31,8 +32,14 @@
     return;
   }
 
-  // Disallow secondary sign-in by enabling Mirror consistency.
+  // Disallow secondary sign-in by enabling Mirror consistency. If Chrome OS
+  // Account Manager is not available, this has the effect of disabling
+  // secondary account sign-ins within the content area.
+  // TODO(https://crbug.com/938835): Clean this up after releasing Chrome OS
+  // Account Manager.
   prefs->SetBoolean(prefs::kAccountConsistencyMirrorRequired, true);
+  prefs->SetBoolean(chromeos::prefs::kSecondaryGoogleAccountSigninAllowed,
+                    false);
 }
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler_unittest.cc b/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler_unittest.cc
index 8f49a58d..de09538 100644
--- a/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler_unittest.cc
+++ b/chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.h"
+#include "chromeos/constants/chromeos_pref_names.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/policy_constants.h"
@@ -24,7 +25,8 @@
   void SetPolicy(std::unique_ptr<base::Value> value) {
     policies_.Set(key::kSecondaryGoogleAccountSigninAllowed,
                   POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                  POLICY_SOURCE_CLOUD, std::move(value), nullptr);
+                  POLICY_SOURCE_CLOUD, std::move(value),
+                  nullptr /* external_data_fetcher */);
   }
 
   void ApplyPolicySettings(bool value) {
@@ -32,14 +34,31 @@
     handler_.ApplyPolicySettings(policies_, &prefs_);
   }
 
-  bool GetAccountConsistencyPref(bool* pref) {
-    return prefs_.GetBoolean(prefs::kAccountConsistencyMirrorRequired, pref);
+  bool GetMirrorAccountConsistencyPref() {
+    bool pref = false;
+    bool success =
+        prefs_.GetBoolean(prefs::kAccountConsistencyMirrorRequired, &pref);
+    EXPECT_TRUE(success);
+    return pref;
   }
 
   void SetAccountConsistencyPref(bool pref) {
     prefs_.SetBoolean(prefs::kAccountConsistencyMirrorRequired, pref);
   }
 
+  bool GetSecondaryGoogleAccountSigninAllowedPref() {
+    bool pref = false;
+    bool success = prefs_.GetBoolean(
+        chromeos::prefs::kSecondaryGoogleAccountSigninAllowed, &pref);
+    EXPECT_TRUE(success);
+    return pref;
+  }
+
+  void SetSecondaryGoogleAccountSigninPref(bool pref) {
+    prefs_.SetBoolean(chromeos::prefs::kSecondaryGoogleAccountSigninAllowed,
+                      pref);
+  }
+
  private:
   SecondaryGoogleAccountSigninPolicyHandler handler_;
   PolicyMap policies_;
@@ -48,33 +67,50 @@
   DISALLOW_COPY_AND_ASSIGN(SecondaryGoogleAccountSigninPolicyHandlerTest);
 };
 
+// If the policy is set to true, it should not override the default pref values
+// (set to true in this test case).
 TEST_F(SecondaryGoogleAccountSigninPolicyHandlerTest,
-       CheckSigninAllowedDoesNotChangeDefaultTruePreference) {
+       SettingPolicyToTrueDoesNotChangeDefaultPreferencesSetToTrue) {
+  // Set prefs to |true|.
   SetAccountConsistencyPref(true);
+  SetSecondaryGoogleAccountSigninPref(true);
+  // Set policy to |true|.
   ApplyPolicySettings(true /* policy value */);
 
-  bool preference = false;
-  EXPECT_TRUE(GetAccountConsistencyPref(&preference));
-  EXPECT_TRUE(preference);
+  // Test that the prefs should be set to |true|.
+  EXPECT_TRUE(GetMirrorAccountConsistencyPref());
+  EXPECT_TRUE(GetSecondaryGoogleAccountSigninAllowedPref());
 }
 
+// If the policy is set to true, it should not override the default pref values
+// (set to false in this test case).
 TEST_F(SecondaryGoogleAccountSigninPolicyHandlerTest,
-       CheckSigninAllowedDoesNotChangeDefaultFalsePreference) {
+       SettingPolicyToTrueDoesNotChangeDefaultPreferencesSetToFalse) {
+  // Set prefs to |false|.
   SetAccountConsistencyPref(false);
+  SetSecondaryGoogleAccountSigninPref(false);
+  // Set policy to |true|.
   ApplyPolicySettings(true /* policy value */);
 
-  bool preference = true;
-  EXPECT_TRUE(GetAccountConsistencyPref(&preference));
-  EXPECT_FALSE(preference);
+  // Test that the prefs should be set to |false|.
+  EXPECT_FALSE(GetMirrorAccountConsistencyPref());
+  EXPECT_FALSE(GetSecondaryGoogleAccountSigninAllowedPref());
 }
 
 TEST_F(SecondaryGoogleAccountSigninPolicyHandlerTest,
-       CheckSigninDisallowedEnablesMirror) {
+       SettingPolicyToFalseEnablesMirror) {
+  SetAccountConsistencyPref(false);
   ApplyPolicySettings(false /* policy value */);
 
-  bool preference = false;
-  EXPECT_TRUE(GetAccountConsistencyPref(&preference));
-  EXPECT_TRUE(preference);
+  EXPECT_TRUE(GetMirrorAccountConsistencyPref());
+}
+
+TEST_F(SecondaryGoogleAccountSigninPolicyHandlerTest,
+       SettingPolicyToFalseDisablesSecondaryAccountSignins) {
+  SetSecondaryGoogleAccountSigninPref(true);
+  ApplyPolicySettings(false /* policy value */);
+
+  EXPECT_FALSE(GetSecondaryGoogleAccountSigninAllowedPref());
 }
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
index baa2e5cc..8b8f4a8fd 100644
--- a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
+++ b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
@@ -27,6 +27,7 @@
 #include "chromeos/dbus/fake_cryptohome_client.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/user_manager/user.h"
@@ -164,6 +165,10 @@
     chromeos::DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient(
         std::make_unique<chromeos::FakeCryptohomeClient>());
 
+    // Initialize UpstartClient here so that it is available for
+    // FakeAuthPolicyClient. It will be shutdown in ChromeBrowserMain.
+    chromeos::UpstartClient::InitializeFake();
+
     chromeos::FakeAuthPolicyClient* fake_auth_policy_client = nullptr;
     if (GetParam().active_directory) {
       auto fake_auth_policy_client_owned =
diff --git a/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc b/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc
index 8dad42f5..650db39 100644
--- a/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc
+++ b/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc
@@ -27,9 +27,9 @@
 
 // IppEverywhere printers are also required to advertise these services.
 const char ZeroconfPrinterDetector::kIppEverywhereServiceName[] =
-    "_ipp._tcp.local,_print";
+    "_print._sub._ipp._tcp.local";
 const char ZeroconfPrinterDetector::kIppsEverywhereServiceName[] =
-    "_ipps._tcp.local,_print";
+    "_print._sub._ipps._tcp.local";
 
 namespace {
 
@@ -127,7 +127,8 @@
 // Attempt to fill |detected_printer| using the information in
 // |service_description| and |metadata|.  Return true on success, false on
 // failure.
-bool ConvertToPrinter(const ServiceDescription& service_description,
+bool ConvertToPrinter(const std::string& service_type,
+                      const ServiceDescription& service_description,
                       const ParsedMetadata& metadata,
                       PrinterDetector::DetectedPrinter* detected_printer) {
   // If we don't have the minimum information needed to attempt a setup, fail.
@@ -145,7 +146,6 @@
   printer.set_display_name(metadata.ty);
   printer.set_description(metadata.note);
   printer.set_make_and_model(metadata.product);
-  const std::string service_type = service_description.service_type();
   const char* uri_protocol;
   if (service_type == ZeroconfPrinterDetector::kIppServiceName ||
       service_type == ZeroconfPrinterDetector::kIppEverywhereServiceName) {
@@ -173,13 +173,13 @@
       service_description.address.port(), metadata.rp.c_str()));
 
   // Per the IPP Everywhere Standard 5100.14-2013, section 4.2.1, IPP
-  // everywhere-capable printers advertise services suffixed with ",_print"
-  // (possibly in addition to suffix-free versions).  If we get a printer from a
-  // ,_print service type, it should be auto-configurable with IPP Everywhere.
+  // everywhere-capable printers advertise services prefixed with "_print"
+  // (possibly in addition to prefix-free versions).  If we get a printer from a
+  // _print service type, it should be auto-configurable with IPP Everywhere.
   printer.mutable_ppd_reference()->autoconf =
-      base::StringPiece(service_type).ends_with(",_print");
+      base::StringPiece(service_type).starts_with("_print._sub");
 
-  // gather ppd identification candidates.
+  // Gather ppd identification candidates.
   detected_printer->ppd_search_data.discovery_type =
       PrinterSearchData::PrinterDiscoveryType::kZeroconf;
   if (!metadata.ty.empty()) {
@@ -259,7 +259,8 @@
     // We don't care if it was added or not; we generate an update either way.
     ParsedMetadata metadata(service_description);
     DetectedPrinter printer;
-    if (!ConvertToPrinter(service_description, metadata, &printer)) {
+    if (!ConvertToPrinter(service_type, service_description, metadata,
+                          &printer)) {
       return;
     }
     base::AutoLock auto_lock(printers_lock_);
diff --git a/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc b/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc
index 3f3c115d..69eccea 100644
--- a/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc
+++ b/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc
@@ -176,9 +176,6 @@
 
 }  // namespace
 
-// static
-constexpr base::TimeDelta ModuleBlacklistCacheUpdater::kUpdateTimerDuration;
-
 ModuleBlacklistCacheUpdater::ModuleBlacklistCacheUpdater(
     ModuleDatabaseEventSource* module_database_event_source,
     const CertificateInfo& exe_certificate_info,
@@ -312,12 +309,6 @@
   module_analysis_disabled_ = true;
 }
 
-void ModuleBlacklistCacheUpdater::OnTimerExpired() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  StartModuleBlacklistCacheUpdate();
-}
-
 ModuleBlacklistCacheUpdater::ModuleListState
 ModuleBlacklistCacheUpdater::DetermineModuleListState(
     const ModuleInfoKey& module_key,
diff --git a/chrome/browser/conflicts/module_blacklist_cache_updater_win.h b/chrome/browser/conflicts/module_blacklist_cache_updater_win.h
index 03c709b..2054103 100644
--- a/chrome/browser/conflicts/module_blacklist_cache_updater_win.h
+++ b/chrome/browser/conflicts/module_blacklist_cache_updater_win.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include "base/callback.h"
 #include "base/containers/flat_map.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
@@ -14,8 +15,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
 #include "chrome/browser/conflicts/module_database_observer_win.h"
 #include "chrome/browser/conflicts/proto/module_list.pb.h"
 #include "chrome_elf/third_party_dlls/packed_list_format.h"
@@ -31,15 +30,8 @@
 // is used by chrome_elf.dll to determine which module to block from loading
 // into the process.
 //
-// Two things can happen that requires an update to the cache:
-//   1. The Module Database becomes idle and this class identified new
-//      blacklisted modules. They must be added to the cache.
-//   2. The module load attempt log was drained and contained blocked entries.
-//      Their timestamp in the cache must be updated.
-//
-// To coalesce these events and reduce the number of updates, a timer is started
-// when the load attempt log is drained. Once expired, an update is triggered
-// unless one was already done because of newly blacklisted modules.
+// The cache is updated everytime the module database becomes idle and at least
+// one module must be added to the cache.
 //
 //
 // Additional implementation details about the module blacklist cache file:
@@ -147,11 +139,6 @@
   using OnCacheUpdatedCallback =
       base::RepeatingCallback<void(const CacheUpdateResult&)>;
 
-  // The amount of time the timer will run before triggering an update of the
-  // cache.
-  static constexpr base::TimeDelta kUpdateTimerDuration =
-      base::TimeDelta::FromMinutes(2);
-
   // Creates an instance of the updater. The callback will be invoked every time
   // the cache is updated.
   // The parameters must outlive the lifetime of this class.
@@ -207,8 +194,6 @@
     kBlacklisted,
   };
 
-  void OnTimerExpired();
-
   // Gets the state of a module with respect to the module list.
   ModuleListState DetermineModuleListState(const ModuleInfoKey& module_key,
                                            const ModuleInfoData& module_data);
@@ -245,10 +230,6 @@
   // until they are used to update the cache.
   std::vector<third_party_dlls::PackedListModule> blocked_modules_;
 
-  // Ensures that the cache is updated when new blocked modules arrives even if
-  // OnModuleDatabaseIdle() is never called again.
-  base::OneShotTimer timer_;
-
   // Holds the blocking state for all known modules.
   base::flat_map<ModuleInfoKey, ModuleBlockingState> module_blocking_states_;
 
diff --git a/chrome/browser/devtools/chrome_devtools_session.cc b/chrome/browser/devtools/chrome_devtools_session.cc
index 80388aa3..42b6cee6 100644
--- a/chrome/browser/devtools/chrome_devtools_session.cc
+++ b/chrome/browser/devtools/chrome_devtools_session.cc
@@ -11,6 +11,7 @@
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_agent_host_client.h"
 #include "content/public/browser/devtools_manager_delegate.h"
+#include "content/public/common/content_switches.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/devtools/protocol/window_manager_handler.h"
@@ -52,6 +53,12 @@
   client_->DispatchProtocolMessage(agent_host_, message->serialize(binary));
 }
 
+static bool EnableInternalDevToolsBinaryProtocol() {
+  static bool enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableInternalDevToolsBinaryProtocol);
+  return enabled;
+}
+
 void ChromeDevToolsSession::HandleCommand(
     const std::string& method,
     const std::string& message,
@@ -63,9 +70,14 @@
 
   int call_id;
   std::string unused;
+  // We also check for --enable-internal-dev-tools-binary-protocol here,
+  // because if this flag is set, then content::DevToolsSession will
+  // send us binary even if the |client_| did not ask for it.
+  bool binary =
+      client_->UsesBinaryProtocol() || EnableInternalDevToolsBinaryProtocol();
   std::unique_ptr<protocol::DictionaryValue> value =
-      protocol::DictionaryValue::cast(protocol::StringUtil::parseMessage(
-          message, client_->UsesBinaryProtocol()));
+      protocol::DictionaryValue::cast(
+          protocol::StringUtil::parseMessage(message, binary));
   if (!dispatcher_->parseCommand(value.get(), &call_id, &unused))
     return;
   pending_commands_[call_id] = std::move(callback);
diff --git a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
index 16b2359..d5c1ecb 100644
--- a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
@@ -14,7 +14,9 @@
 #include "chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h"
 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
 #include "chrome/browser/extensions/extension_util.h"
+#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
 #include "extensions/browser/api/declarative_net_request/test_utils.h"
 #include "extensions/browser/api/web_request/web_request_info.h"
 #include "extensions/browser/extension_prefs.h"
@@ -45,11 +47,11 @@
  protected:
   using Action = RulesetManager::Action;
 
-  // Helper to create a ruleset matcher instance for the given |rules|.
+  // Helper to create a composite matcher instance for the given |rules|.
   void CreateMatcherForRules(
       const std::vector<TestRule>& rules,
       const std::string& extension_dirname,
-      std::unique_ptr<RulesetMatcher>* matcher,
+      std::unique_ptr<CompositeMatcher>* matcher,
       const std::vector<std::string>& host_permissions = {},
       bool has_background_script = false) {
     base::FilePath extension_dir =
@@ -74,11 +76,12 @@
                     ->GetDNRRulesetChecksum(last_loaded_extension_->id(),
                                             &expected_checksum));
 
-    EXPECT_EQ(
-        RulesetMatcher::kLoadSuccess,
-        RulesetMatcher::CreateVerifiedMatcher(
-            file_util::GetIndexedRulesetPath(last_loaded_extension_->path()),
-            expected_checksum, matcher));
+    std::vector<std::unique_ptr<RulesetMatcher>> matchers(1);
+    EXPECT_EQ(RulesetMatcher::kLoadSuccess,
+              RulesetMatcher::CreateVerifiedMatcher(
+                  RulesetSource::Create(*last_loaded_extension_),
+                  expected_checksum, &matchers[0]));
+    *matcher = std::make_unique<CompositeMatcher>(std::move(matchers));
   }
 
   void SetIncognitoEnabled(const Extension* extension, bool incognito_enabled) {
@@ -155,7 +158,7 @@
     // Add the required rulesets.
     if (mask & kEnableRulesetOne) {
       ++expected_matcher_count;
-      std::unique_ptr<RulesetMatcher> matcher;
+      std::unique_ptr<CompositeMatcher> matcher;
       ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
           {rule_one}, std::to_string(mask) + "_one", &matcher));
       extension_id_one = last_loaded_extension()->id();
@@ -164,7 +167,7 @@
     }
     if (mask & kEnableRulesetTwo) {
       ++expected_matcher_count;
-      std::unique_ptr<RulesetMatcher> matcher;
+      std::unique_ptr<CompositeMatcher> matcher;
       ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
           {rule_two}, std::to_string(mask) + "_two", &matcher));
       extension_id_two = last_loaded_extension()->id();
@@ -197,7 +200,7 @@
   // Add an extension ruleset blocking "example.com".
   TestRule rule_one = CreateGenericRule();
   rule_one.condition->url_filter = std::string("example.com");
-  std::unique_ptr<RulesetMatcher> matcher;
+  std::unique_ptr<CompositeMatcher> matcher;
   ASSERT_NO_FATAL_FAILURE(
       CreateMatcherForRules({rule_one}, "test_extension", &matcher));
   manager->AddRuleset(last_loaded_extension()->id(), std::move(matcher),
@@ -258,7 +261,7 @@
   // Add an extension ruleset which blocks requests to "example.com".
   TestRule rule = CreateGenericRule();
   rule.condition->url_filter = std::string("example.com");
-  std::unique_ptr<RulesetMatcher> matcher;
+  std::unique_ptr<CompositeMatcher> matcher;
   ASSERT_NO_FATAL_FAILURE(
       CreateMatcherForRules({rule}, "test_extension", &matcher));
   manager->AddRuleset(last_loaded_extension()->id(), std::move(matcher),
@@ -288,7 +291,7 @@
   rule.priority = kMinValidPriority;
   rule.action->type = std::string("redirect");
   rule.action->redirect_url = std::string("http://google.com");
-  std::unique_ptr<RulesetMatcher> matcher;
+  std::unique_ptr<CompositeMatcher> matcher;
   ASSERT_NO_FATAL_FAILURE(
       CreateMatcherForRules({rule}, "test_extension", &matcher,
                             {"*://example.com/*", "*://abc.com/*"}));
@@ -340,7 +343,7 @@
   const Extension* extension_2 = nullptr;
   // Add an extension with a background page which blocks all requests.
   {
-    std::unique_ptr<RulesetMatcher> matcher;
+    std::unique_ptr<CompositeMatcher> matcher;
     TestRule rule = CreateGenericRule();
     rule.condition->url_filter = std::string("*");
     ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
@@ -354,7 +357,7 @@
   // Add another extension with a background page which redirects all requests
   // to "http://google.com".
   {
-    std::unique_ptr<RulesetMatcher> matcher;
+    std::unique_ptr<CompositeMatcher> matcher;
     TestRule rule = CreateGenericRule();
     rule.condition->url_filter = std::string("*");
     rule.priority = kMinValidPriority;
@@ -412,7 +415,7 @@
   // Add an extension which blocks all requests except for requests from
   // http://google.com/allow* which are allowed.
   {
-    std::unique_ptr<RulesetMatcher> matcher;
+    std::unique_ptr<CompositeMatcher> matcher;
 
     // This blocks all subresource requests. By default the main-frame resource
     // type is excluded.
@@ -575,7 +578,7 @@
   // Add an extension which redirects all sub-resource and sub-frame requests
   // made to example.com, to foo.com. By default, the "main_frame" type is
   // excluded if no "resource_types" are specified.
-  std::unique_ptr<RulesetMatcher> redirect_matcher;
+  std::unique_ptr<CompositeMatcher> redirect_matcher;
   {
     TestRule rule = CreateGenericRule();
     rule.id = kMinValidID;
@@ -594,7 +597,7 @@
   // Add an extension which blocks all sub-resource and sub-frame requests to
   // example.com. By default, the "main_frame" type is excluded if no
   // "resource_types" are specified. The extension has no host permissions.
-  std::unique_ptr<RulesetMatcher> blocking_matcher;
+  std::unique_ptr<CompositeMatcher> blocking_matcher;
   {
     TestRule rule = CreateGenericRule();
     rule.id = kMinValidID;
diff --git a/chrome/browser/extensions/global_shortcut_listener_win.cc b/chrome/browser/extensions/global_shortcut_listener_win.cc
index eb58c51..f5d0ac4 100644
--- a/chrome/browser/extensions/global_shortcut_listener_win.cc
+++ b/chrome/browser/extensions/global_shortcut_listener_win.cc
@@ -93,12 +93,18 @@
     return success;
   }
 
+  // Convert Accelerator modifiers to OS modifiers.
+  int modifiers = 0;
+  modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0;
+  modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0;
+  modifiers |= accelerator.IsAltDown() ? MOD_ALT : 0;
+
   // Create an observer that registers a hot key for |accelerator|.
   std::unique_ptr<gfx::SingletonHwndHotKeyObserver> observer =
       gfx::SingletonHwndHotKeyObserver::Create(
           base::BindRepeating(&GlobalShortcutListenerWin::OnWndProc,
                               base::Unretained(this)),
-          accelerator.key_code(), accelerator.modifiers());
+          accelerator.key_code(), modifiers);
 
   if (!observer) {
     // Most likely error: 1409 (Hotkey already registered).
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index d684f6b..a523b4a 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1323,8 +1323,8 @@
   },
   {
     "name": "enable-modal-permission-dialog-view",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "pavely" ],
+    "expiry_milestone": 75
   },
   {
     "name": "enable-myfiles-volume",
@@ -1482,11 +1482,6 @@
     "expiry_milestone": 76
   },
   {
-    "name": "enable-per-user-timezone",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "enable-physical-keyboard-autocorrect",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
@@ -2167,6 +2162,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "installable-ink-drop",
+    "owners": [ "collinbaker", "pbos" ],
+    "expiry_milestone": 77
+  },
+  {
     "name": "instant-tethering",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d3830f0..019e830f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3202,11 +3202,6 @@
     "Enable the Recommend Apps Screen in OOBE which allows user to install apps"
     "from other devices";
 
-const char kEnablePerUserTimezoneName[] = "Per-user time zone preferences.";
-const char kEnablePerUserTimezoneDescription[] =
-    "Chrome OS system timezone preference is stored and handled for each user "
-    "individually.";
-
 const char kEnablePlayStoreSearchName[] = "Enable Play Store search";
 const char kEnablePlayStoreSearchDescription[] =
     "Enable Play Store search in launcher.";
@@ -3463,6 +3458,17 @@
 
 #endif  // defined(OS_CHROMEOS)
 
+// All views-based platforms --------------------------------------------------
+
+#if defined(TOOLKIT_VIEWS)
+
+const char kInstallableInkDropName[] = "Use InstallableInkDrop where supported";
+const char kInstallableInkDropDescription[] =
+    "InstallableInkDrop is part of an InkDrop refactoring effort. This enables "
+    "the pilot implementation where available.";
+
+#endif  // defined(TOOLKIT_VIEWS)
+
 // Random platform combinations -----------------------------------------------
 
 #if defined(OS_WIN) || defined(OS_LINUX)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 21a601d..7177546 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1916,9 +1916,6 @@
 extern const char kEnableOobeRecommendAppsScreenName[];
 extern const char kEnableOobeRecommendAppsScreenDescription[];
 
-extern const char kEnablePerUserTimezoneName[];
-extern const char kEnablePerUserTimezoneDescription[];
-
 extern const char kEnablePlayStoreSearchName[];
 extern const char kEnablePlayStoreSearchDescription[];
 
@@ -2073,6 +2070,15 @@
 
 #endif  // #if defined(OS_CHROMEOS)
 
+// All views-based platforms --------------------------------------------------
+
+#if defined(TOOLKIT_VIEWS)
+
+extern const char kInstallableInkDropName[];
+extern const char kInstallableInkDropDescription[];
+
+#endif  // defined(TOOLKIT_VIEWS)
+
 // Random platform combinations -----------------------------------------------
 
 #if defined(OS_WIN) || defined(OS_LINUX)
diff --git a/chrome/browser/gcm/gcm_profile_service_factory.cc b/chrome/browser/gcm/gcm_profile_service_factory.cc
index 6d54d1db..27a212a 100644
--- a/chrome/browser/gcm/gcm_profile_service_factory.cc
+++ b/chrome/browser/gcm/gcm_profile_service_factory.cc
@@ -155,7 +155,7 @@
       offline_pages::PrefetchServiceFactory::GetForBrowserContext(context);
   if (prefetch_service != nullptr) {
     offline_pages::PrefetchGCMHandler* prefetch_gcm_handler =
-        prefetch_service->GetPrefetchGCMHandler();
+        prefetch_service->GetOrCreatePrefetchGCMHandler(context);
     service->driver()->AddAppHandler(prefetch_gcm_handler->GetAppId(),
                                      prefetch_gcm_handler->AsGCMAppHandler());
   }
diff --git a/chrome/browser/installable/installable_manager.cc b/chrome/browser/installable/installable_manager.cc
index 5284576..8f95112 100644
--- a/chrome/browser/installable/installable_manager.cc
+++ b/chrome/browser/installable/installable_manager.cc
@@ -21,6 +21,7 @@
 #include "content/public/common/origin_util.h"
 #include "content/public/common/url_constants.h"
 #include "net/base/url_util.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
 #include "third_party/blink/public/common/manifest/web_display_mode.h"
 #include "url/origin.h"
@@ -83,7 +84,8 @@
   // Check those explicitly, using the VisibleURL to match what
   // SecurityStateTabHelper looks at.
   if (net::IsLocalhost(url) ||
-      content::IsWhitelistedAsSecureOrigin(url::Origin::Create(url))) {
+      network::IsAllowlistedAsSecureOrigin(
+          url::Origin::Create(url), network::GetSecureOriginAllowlist())) {
     return true;
   }
 
diff --git a/chrome/browser/net/DEPS b/chrome/browser/net/DEPS
index 33ac7c87..35ecf445 100644
--- a/chrome/browser/net/DEPS
+++ b/chrome/browser/net/DEPS
@@ -1,7 +1,3 @@
-include_rules = [
-  "+services/network/session_cleanup_channel_id_store.h",
-]
-
 specific_include_rules = {
   '.*_[a-z]*test.*': [
     "+services/network/test",
diff --git a/chrome/browser/net/quota_policy_channel_id_store.cc b/chrome/browser/net/quota_policy_channel_id_store.cc
deleted file mode 100644
index d91bc69..0000000
--- a/chrome/browser/net/quota_policy_channel_id_store.cc
+++ /dev/null
@@ -1,27 +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.
-
-#include "chrome/browser/net/quota_policy_channel_id_store.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "storage/browser/quota/special_storage_policy.h"
-
-QuotaPolicyChannelIDStore::QuotaPolicyChannelIDStore(
-    const base::FilePath& path,
-    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
-    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy)
-    : SessionCleanupChannelIDStore(path, background_task_runner),
-      special_storage_policy_(special_storage_policy) {}
-
-QuotaPolicyChannelIDStore::~QuotaPolicyChannelIDStore() {
-  if (!special_storage_policy_.get() ||
-      !special_storage_policy_->HasSessionOnlyOrigins()) {
-    return;
-  }
-
-  DeleteSessionChannelIDs(
-      base::BindRepeating(&storage::SpecialStoragePolicy::IsStorageSessionOnly,
-                          special_storage_policy_));
-}
diff --git a/chrome/browser/net/quota_policy_channel_id_store.h b/chrome/browser/net/quota_policy_channel_id_store.h
deleted file mode 100644
index 230da33..0000000
--- a/chrome/browser/net/quota_policy_channel_id_store.h
+++ /dev/null
@@ -1,44 +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 CHROME_BROWSER_NET_QUOTA_POLICY_CHANNEL_ID_STORE_H_
-#define CHROME_BROWSER_NET_QUOTA_POLICY_CHANNEL_ID_STORE_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "net/extras/sqlite/sqlite_channel_id_store.h"
-#include "services/network/session_cleanup_channel_id_store.h"
-
-namespace base {
-class FilePath;
-class SequencedTaskRunner;
-}
-
-namespace storage {
-class SpecialStoragePolicy;
-}
-
-// Persistent ChannelID Store that takes into account SpecialStoragePolicy and
-// removes ChannelIDs that are StorageSessionOnly when store is closed.
-class QuotaPolicyChannelIDStore : public network::SessionCleanupChannelIDStore {
- public:
-  // Create or open persistent store in file |path|. All I/O tasks are performed
-  // in background using |background_task_runner|. If provided, a
-  // |special_storage_policy| is consulted when the store is closed to decide
-  // which certificates to keep.
-  QuotaPolicyChannelIDStore(
-      const base::FilePath& path,
-      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
-      const scoped_refptr<storage::SpecialStoragePolicy>&
-          special_storage_policy);
-
- private:
-  ~QuotaPolicyChannelIDStore() override;
-
-  scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuotaPolicyChannelIDStore);
-};
-
-#endif  // CHROME_BROWSER_NET_QUOTA_POLICY_CHANNEL_ID_STORE_H_
diff --git a/chrome/browser/net/quota_policy_channel_id_store_unittest.cc b/chrome/browser/net/quota_policy_channel_id_store_unittest.cc
deleted file mode 100644
index f28647d..0000000
--- a/chrome/browser/net/quota_policy_channel_id_store_unittest.cc
+++ /dev/null
@@ -1,192 +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.
-
-#include "chrome/browser/net/quota_policy_channel_id_store.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/cookies/cookie_util.h"
-#include "net/ssl/ssl_client_cert_type.h"
-#include "net/test/cert_test_util.h"
-#include "net/test/channel_id_test_util.h"
-#include "net/test/test_data_directory.h"
-#include "sql/statement.h"
-#include "storage/browser/test/mock_special_storage_policy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-const base::FilePath::CharType kTestChannelIDFilename[] =
-    FILE_PATH_LITERAL("ChannelID");
-
-class QuotaPolicyChannelIDStoreTest : public testing::Test {
- public:
-  void Load(std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>*
-                channel_ids) {
-    base::RunLoop run_loop;
-    store_->Load(base::Bind(&QuotaPolicyChannelIDStoreTest::OnLoaded,
-                            base::Unretained(this),
-                            &run_loop));
-    run_loop.Run();
-    channel_ids->swap(channel_ids_);
-    channel_ids_.clear();
-  }
-
-  void OnLoaded(
-      base::RunLoop* run_loop,
-      std::unique_ptr<
-          std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>>
-          channel_ids) {
-    channel_ids_.swap(*channel_ids);
-    run_loop->Quit();
-  }
-
- protected:
-  void SetUp() override {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    store_ = new QuotaPolicyChannelIDStore(
-        temp_dir_.GetPath().Append(kTestChannelIDFilename),
-        base::ThreadTaskRunnerHandle::Get(), NULL);
-    std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>
-        channel_ids;
-    Load(&channel_ids);
-    ASSERT_EQ(0u, channel_ids.size());
-  }
-
-  void TearDown() override {
-    store_ = NULL;
-    base::RunLoop().RunUntilIdle();
-  }
-
-  base::ScopedTempDir temp_dir_;
-  scoped_refptr<QuotaPolicyChannelIDStore> store_;
-  std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>
-      channel_ids_;
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-};
-
-// Test if data is stored as expected in the QuotaPolicy database.
-TEST_F(QuotaPolicyChannelIDStoreTest, TestPersistence) {
-  std::unique_ptr<crypto::ECPrivateKey> goog_key(
-      crypto::ECPrivateKey::Create());
-  std::unique_ptr<crypto::ECPrivateKey> foo_key(crypto::ECPrivateKey::Create());
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "google.com", base::Time::FromInternalValue(1), goog_key->Copy()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "foo.com", base::Time::FromInternalValue(3), foo_key->Copy()));
-
-  std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>
-      channel_ids;
-  // Replace the store effectively destroying the current one and forcing it
-  // to write its data to disk. Then we can see if after loading it again it
-  // is still there.
-  store_ = NULL;
-  // Make sure we wait until the destructor has run.
-  base::RunLoop().RunUntilIdle();
-  store_ = new QuotaPolicyChannelIDStore(
-      temp_dir_.GetPath().Append(kTestChannelIDFilename),
-      base::ThreadTaskRunnerHandle::Get(), NULL);
-
-  // Reload and test for persistence
-  Load(&channel_ids);
-  ASSERT_EQ(2U, channel_ids.size());
-  net::DefaultChannelIDStore::ChannelID* goog_channel_id;
-  net::DefaultChannelIDStore::ChannelID* foo_channel_id;
-  if (channel_ids[0]->server_identifier() == "google.com") {
-    goog_channel_id = channel_ids[0].get();
-    foo_channel_id = channel_ids[1].get();
-  } else {
-    goog_channel_id = channel_ids[1].get();
-    foo_channel_id = channel_ids[0].get();
-  }
-  ASSERT_EQ("google.com", goog_channel_id->server_identifier());
-  EXPECT_TRUE(net::KeysEqual(goog_key.get(), goog_channel_id->key()));
-  ASSERT_EQ(1, goog_channel_id->creation_time().ToInternalValue());
-  ASSERT_EQ("foo.com", foo_channel_id->server_identifier());
-  EXPECT_TRUE(net::KeysEqual(foo_key.get(), foo_channel_id->key()));
-  ASSERT_EQ(3, foo_channel_id->creation_time().ToInternalValue());
-
-  // Now delete the channel ID and check persistence again.
-  store_->DeleteChannelID(*channel_ids[0]);
-  store_->DeleteChannelID(*channel_ids[1]);
-  store_ = NULL;
-  // Make sure we wait until the destructor has run.
-  base::RunLoop().RunUntilIdle();
-  channel_ids.clear();
-  store_ = new QuotaPolicyChannelIDStore(
-      temp_dir_.GetPath().Append(kTestChannelIDFilename),
-      base::ThreadTaskRunnerHandle::Get(), NULL);
-
-  // Reload and check if the channel ID has been removed.
-  Load(&channel_ids);
-  ASSERT_EQ(0U, channel_ids.size());
-}
-
-// Test if data is stored as expected in the QuotaPolicy database.
-TEST_F(QuotaPolicyChannelIDStoreTest, TestPolicy) {
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "google.com", base::Time::FromInternalValue(1),
-      crypto::ECPrivateKey::Create()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "nonpersistent.com", base::Time::FromInternalValue(3),
-      crypto::ECPrivateKey::Create()));
-
-  std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>
-      channel_ids;
-  // Replace the store effectively destroying the current one and forcing it
-  // to write its data to disk. Then we can see if after loading it again it
-  // is still there.
-  store_ = NULL;
-  // Make sure we wait until the destructor has run.
-  base::RunLoop().RunUntilIdle();
-  // Specify storage policy that makes "nonpersistent.com" session only.
-  scoped_refptr<content::MockSpecialStoragePolicy> storage_policy =
-      new content::MockSpecialStoragePolicy();
-  storage_policy->AddSessionOnly(
-      net::cookie_util::CookieOriginToURL("nonpersistent.com", true));
-  // Reload store, it should still have both channel IDs.
-  store_ = new QuotaPolicyChannelIDStore(
-      temp_dir_.GetPath().Append(kTestChannelIDFilename),
-      base::ThreadTaskRunnerHandle::Get(), storage_policy);
-  Load(&channel_ids);
-  ASSERT_EQ(2U, channel_ids.size());
-
-  // Add another two channel IDs before closing the store. Because additions are
-  // delayed and committed to disk in batches, these will not be committed until
-  // the store is destroyed, which is after the policy is applied. The pending
-  // operation pruning logic should prevent the "nonpersistent.com" ID from
-  // being committed to disk.
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "nonpersistent.com", base::Time::FromInternalValue(5),
-      crypto::ECPrivateKey::Create()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "persistent.com", base::Time::FromInternalValue(7),
-      crypto::ECPrivateKey::Create()));
-
-  // Now close the store, and the nonpersistent.com channel IDs should be
-  // deleted according to policy.
-  store_ = NULL;
-  // Make sure we wait until the destructor has run.
-  base::RunLoop().RunUntilIdle();
-  channel_ids.clear();
-  store_ = new QuotaPolicyChannelIDStore(
-      temp_dir_.GetPath().Append(kTestChannelIDFilename),
-      base::ThreadTaskRunnerHandle::Get(), NULL);
-
-  // Reload and check that the nonpersistent.com channel IDs have been removed.
-  Load(&channel_ids);
-  ASSERT_EQ(2U, channel_ids.size());
-  for (const auto& id : channel_ids) {
-    ASSERT_NE("nonpersistent.com", id->server_identifier());
-  }
-}
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
index 8c9693c..b95185e8 100644
--- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
+++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -41,6 +41,18 @@
 
 namespace offline_pages {
 
+namespace {
+
+std::unique_ptr<PrefetchGCMHandler> CreatePrefetchGCMHandler(
+    content::BrowserContext* context) {
+  DCHECK(context);
+  return std::make_unique<PrefetchGCMAppHandler>(
+      std::make_unique<PrefetchInstanceIDProxy>(kPrefetchingOfflinePagesAppId,
+                                                context));
+}
+
+}  // namespace
+
 PrefetchServiceFactory::PrefetchServiceFactory()
     : BrowserContextKeyedServiceFactory(
           "OfflinePagePrefetchService",
@@ -80,9 +92,8 @@
   auto prefetch_dispatcher =
       std::make_unique<PrefetchDispatcherImpl>(profile->GetPrefs());
 
-  auto prefetch_gcm_app_handler = std::make_unique<PrefetchGCMAppHandler>(
-      std::make_unique<PrefetchInstanceIDProxy>(kPrefetchingOfflinePagesAppId,
-                                                context));
+  auto create_prefetch_gcm_handler_closure =
+      base::BindOnce(&CreatePrefetchGCMHandler);
 
   auto prefetch_network_request_factory =
       std::make_unique<PrefetchNetworkRequestFactoryImpl>(
@@ -126,7 +137,7 @@
 
   return new PrefetchServiceImpl(
       std::move(offline_metrics_collector), std::move(prefetch_dispatcher),
-      std::move(prefetch_gcm_app_handler),
+      std::move(create_prefetch_gcm_handler_closure),
       std::move(prefetch_network_request_factory), offline_page_model,
       std::move(prefetch_store), std::move(suggested_articles_observer),
       std::move(prefetch_downloader), std::move(prefetch_importer),
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
index e73f48e..0ec9c4a 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -6,11 +6,16 @@
 
 #include <cmath>
 #include <memory>
+#include <vector>
 
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
+#include "chrome/browser/prerender/prerender_final_status.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_manager_factory.h"
+#include "chrome/browser/prerender/prerender_origin.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/metrics/net/network_metrics_provider.h"
 #include "content/public/browser/web_contents.h"
@@ -136,6 +141,7 @@
   was_cached_ = navigation_handle->WasResponseCached();
   is_signed_exchange_inner_response_ =
       navigation_handle->IsSignedExchangeInnerResponse();
+  RecordNoStatePrefetchMetrics(navigation_handle, source_id);
   return CONTINUE_OBSERVING;
 }
 
@@ -521,3 +527,43 @@
   largest_contentful_paint_handler_.RecordTiming(timing.paint_timing,
                                                  subframe_rfh);
 }
+
+void UkmPageLoadMetricsObserver::RecordNoStatePrefetchMetrics(
+    content::NavigationHandle* navigation_handle,
+    ukm::SourceId source_id) {
+  prerender::PrerenderManager* const prerender_manager =
+      prerender::PrerenderManagerFactory::GetForBrowserContext(
+          navigation_handle->GetWebContents()->GetBrowserContext());
+  if (!prerender_manager)
+    return;
+
+  const std::vector<GURL>& redirects = navigation_handle->GetRedirectChain();
+
+  base::TimeDelta prefetch_age;
+  prerender::FinalStatus final_status;
+  prerender::Origin prefetch_origin;
+
+  bool nostate_prefetch_entry_found = prerender_manager->GetPrefetchInformation(
+      navigation_handle->GetURL(), &prefetch_age, &final_status,
+      &prefetch_origin);
+
+  // Try the URLs from the redirect chain.
+  if (!nostate_prefetch_entry_found) {
+    for (const auto& url : redirects) {
+      nostate_prefetch_entry_found = prerender_manager->GetPrefetchInformation(
+          url, &prefetch_age, &final_status, &prefetch_origin);
+      if (nostate_prefetch_entry_found)
+        break;
+    }
+  }
+
+  if (!nostate_prefetch_entry_found)
+    return;
+
+  ukm::builders::NoStatePrefetch builder(source_id);
+  builder.SetPrefetchedRecently_PrefetchAge(
+      ukm::GetExponentialBucketMinForUserTiming(prefetch_age.InMilliseconds()));
+  builder.SetPrefetchedRecently_FinalStatus(final_status);
+  builder.SetPrefetchedRecently_Origin(prefetch_origin);
+  builder.Record(ukm::UkmRecorder::Get());
+}
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
index adc490a..648e30a 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_UKM_PAGE_LOAD_METRICS_OBSERVER_H_
 
 #include "base/macros.h"
+#include "base/metrics/ukm_source_id.h"
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h"
@@ -101,6 +102,12 @@
   base::Optional<int64_t> GetRoundedSiteEngagementScore(
       const page_load_metrics::PageLoadExtraInfo& info) const;
 
+  // Records the metrics for the nostate prefetch to an event with UKM source ID
+  // |source_id|.
+  void RecordNoStatePrefetchMetrics(
+      content::NavigationHandle* navigation_handle,
+      ukm::SourceId source_id);
+
   // Guaranteed to be non-null during the lifetime of |this|.
   network::NetworkQualityTracker* network_quality_tracker_;
 
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index ecfa326..dc490b2 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -34,8 +34,12 @@
 #include "chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h"
 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/prerender/prerender_handle.h"
 #include "chrome/browser/prerender/prerender_histograms.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/prerender/prerender_origin.h"
+#include "chrome/browser/prerender/prerender_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_restore.h"
 #include "chrome/browser/sessions/session_restore_test_helper.h"
@@ -83,12 +87,14 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
+#include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
 using page_load_metrics::PageLoadMetricsTestWaiter;
 using TimingField = page_load_metrics::PageLoadMetricsTestWaiter::TimingField;
 using WebFeature = blink::mojom::WebFeature;
 using testing::UnorderedElementsAre;
+using NoStatePrefetch = ukm::builders::NoStatePrefetch;
 
 namespace {
 
@@ -181,6 +187,41 @@
     return std::make_unique<PageLoadMetricsTestWaiter>(web_contents);
   }
 
+  // Triggers nostate prefetch of |url|.
+  void TriggerNoStatePrefetch(const GURL& url) {
+    prerender::PrerenderManager* prerender_manager =
+        prerender::PrerenderManagerFactory::GetForBrowserContext(
+            browser()->profile());
+    ASSERT_TRUE(prerender_manager);
+
+    prerender::test_utils::TestPrerenderContentsFactory*
+        prerender_contents_factory =
+            new prerender::test_utils::TestPrerenderContentsFactory();
+    prerender_manager->SetPrerenderContentsFactoryForTest(
+        prerender_contents_factory);
+
+    content::SessionStorageNamespace* storage_namespace =
+        browser()
+            ->tab_strip_model()
+            ->GetActiveWebContents()
+            ->GetController()
+            .GetDefaultSessionStorageNamespace();
+    ASSERT_TRUE(storage_namespace);
+
+    std::unique_ptr<prerender::test_utils::TestPrerender> test_prerender =
+        prerender_contents_factory->ExpectPrerenderContents(
+            prerender::FINAL_STATUS_NOSTATE_PREFETCH_FINISHED);
+
+    std::unique_ptr<prerender::PrerenderHandle> prerender_handle =
+        prerender_manager->AddPrerenderFromOmnibox(url, storage_namespace,
+                                                   gfx::Size(640, 480));
+    ASSERT_EQ(prerender_handle->contents(), test_prerender->contents());
+
+    // The final status may be either  FINAL_STATUS_NOSTATE_PREFETCH_FINISHED or
+    // FINAL_STATUS_RECENTLY_VISITED.
+    test_prerender->contents()->set_skip_final_checks(true);
+  }
+
   base::test::ScopedFeatureList scoped_feature_list_;
   base::HistogramTester histogram_tester_;
   std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
@@ -263,6 +304,50 @@
         kv.second.get(), PageLoad::kSiteEngagementScoreName));
   }
 
+  const auto& nostate_prefetch_entries =
+      test_ukm_recorder_->GetMergedEntriesByName(NoStatePrefetch::kEntryName);
+  EXPECT_EQ(0u, nostate_prefetch_entries.size());
+
+  // Verify that NoPageLoadMetricsRecorded returns false when PageLoad metrics
+  // have been recorded.
+  EXPECT_FALSE(NoPageLoadMetricsRecorded());
+}
+
+// Triggers nostate prefetch, and verifies that the UKM metrics related to
+// nostate prefetch are recorded correctly.
+IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoStatePrefetchMetrics) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  GURL url = embedded_test_server()->GetURL("/title1.html");
+
+  TriggerNoStatePrefetch(url);
+
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  waiter->AddPageExpectation(TimingField::kFirstPaint);
+  ui_test_utils::NavigateToURL(browser(), url);
+  waiter->Wait();
+
+  // Force navigation to another page, which should force logging of histograms
+  // persisted at the end of the page load lifetime.
+  NavigateToUntrackedUrl();
+  histogram_tester_.ExpectTotalCount(internal::kHistogramPageLoadTotalBytes, 1);
+  histogram_tester_.ExpectTotalCount(
+      internal::kHistogramPageTimingForegroundDuration, 1);
+
+  const auto& entries =
+      test_ukm_recorder_->GetMergedEntriesByName(NoStatePrefetch::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  for (const auto& kv : entries) {
+    test_ukm_recorder_->ExpectEntrySourceHasUrl(kv.second.get(), url);
+    // UKM metrics related to attempted nostate prefetch should be recorded.
+    EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
+        kv.second.get(), NoStatePrefetch::kPrefetchedRecently_FinalStatusName));
+    EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
+        kv.second.get(), NoStatePrefetch::kPrefetchedRecently_OriginName));
+    EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
+        kv.second.get(), NoStatePrefetch::kPrefetchedRecently_PrefetchAgeName));
+  }
+
   // Verify that NoPageLoadMetricsRecorded returns false when PageLoad metrics
   // have been recorded.
   EXPECT_FALSE(NoPageLoadMetricsRecorded());
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index c8f0bf2..a1cf6d1 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -288,6 +288,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chromeos/assistant/buildflags.h"
 #include "chromeos/audio/audio_devices_pref_handler_impl.h"
+#include "chromeos/components/account_manager/account_manager.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/network/fast_transition_observer.h"
 #include "chromeos/network/proxy/proxy_config_handler.h"
@@ -749,6 +750,7 @@
 #if defined(OS_CHROMEOS)
   arc::prefs::RegisterProfilePrefs(registry);
   certificate_manager::CertificatesHandler::RegisterProfilePrefs(registry);
+  chromeos::AccountManager::RegisterPrefs(registry);
   chromeos::CupsPrintersManager::RegisterProfilePrefs(registry);
   chromeos::first_run::RegisterProfilePrefs(registry);
   chromeos::file_system_provider::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
index c72aa73..4cdfaf7 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <string>
 #include <utility>
 #include <vector>
@@ -48,7 +49,7 @@
         {switches::kAuthAndroidNegotiateAccountType,
          prefs::kAuthAndroidNegotiateAccountType},
 #endif
-        {switches::kUnsafelyTreatInsecureOriginAsSecure,
+        {network::switches::kUnsafelyTreatInsecureOriginAsSecure,
          prefs::kUnsafelyTreatInsecureOriginAsSecure},
         // TODO(https://crbug.com/760761): This is not the ideal way to
         // implement this. Refactor enterprise policy and command line handling
diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h
index 3131cc46..9785d2b7 100644
--- a/chrome/browser/prerender/prerender_final_status.h
+++ b/chrome/browser/prerender/prerender_final_status.h
@@ -11,6 +11,11 @@
 
 // FinalStatus indicates whether |this| was used, or why it was cancelled.
 // NOTE: New values need to be appended, since they are used in histograms.
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. The values should remain
+// synchronized with the enum PrerenderFinalStatus in
+// //tools/metrics/histograms/enums.xml.
 enum FinalStatus {
   FINAL_STATUS_USED = 0,
   FINAL_STATUS_TIMED_OUT = 1,
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index d6d856e..2e5a232 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -491,7 +491,8 @@
                                                          base::TimeDelta time) {
   base::TimeDelta prefetch_age;
   Origin origin;
-  GetPrefetchInformation(url, &prefetch_age, &origin);
+  GetPrefetchInformation(url, &prefetch_age, nullptr /* final_status*/,
+                         &origin);
   OnPrefetchUsed(url);
 
   histograms_->RecordPrefetchFirstContentfulPaintTime(
@@ -782,7 +783,8 @@
 
   if (IsNoStatePrefetchEnabled()) {
     base::TimeDelta prefetch_age;
-    GetPrefetchInformation(url, &prefetch_age, nullptr);
+    GetPrefetchInformation(url, &prefetch_age, nullptr /* final_status*/,
+                           nullptr /* origin */);
     if (!prefetch_age.is_zero() &&
         prefetch_age <
             base::TimeDelta::FromMinutes(net::HttpCache::kPrefetchReuseMins)) {
@@ -1028,23 +1030,31 @@
   old_web_contents_list_.clear();
 }
 
-void PrerenderManager::GetPrefetchInformation(const GURL& url,
+bool PrerenderManager::GetPrefetchInformation(const GURL& url,
                                               base::TimeDelta* prefetch_age,
+                                              FinalStatus* final_status,
                                               Origin* origin) {
-  DCHECK(prefetch_age);
   CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30));
 
-  *prefetch_age = base::TimeDelta();
+  if (prefetch_age)
+    *prefetch_age = base::TimeDelta();
+  if (final_status)
+    *final_status = FINAL_STATUS_MAX;
   if (origin)
     *origin = ORIGIN_NONE;
+
   for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) {
     if (it->url == url) {
-      *prefetch_age = GetCurrentTimeTicks() - it->time;
+      if (prefetch_age)
+        *prefetch_age = GetCurrentTimeTicks() - it->time;
+      if (final_status)
+        *final_status = it->final_status;
       if (origin)
         *origin = it->origin;
-      break;
+      return true;
     }
   }
+  return false;
 }
 
 void PrerenderManager::SetPrefetchFinalStatusForUrl(const GURL& url,
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index b190bda..ad7429ee 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -320,6 +320,15 @@
   // content::RenderProcessHostObserver implementation.
   void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
 
+  // Cleans up the expired prefetches and then returns true if |url| was
+  // no-state prefetched recently. If so, |prefetch_age|, |final_status| and
+  // |origin| are set based on the no-state prefetch information if they are
+  // non-null.
+  bool GetPrefetchInformation(const GURL& url,
+                              base::TimeDelta* prefetch_age,
+                              FinalStatus* final_status,
+                              Origin* origin);
+
   void SetPrerenderContentsFactoryForTest(
       PrerenderContents::Factory* prerender_contents_factory);
 
@@ -489,12 +498,6 @@
   // so cannot immediately be deleted.
   void DeleteOldWebContents();
 
-  // Get information associated with a possible prefetch of |url|.
-  // |origin| may be null, in which case the origin is not returned.
-  void GetPrefetchInformation(const GURL& url,
-                              base::TimeDelta* prefetch_age,
-                              Origin* origin);
-
   // Called when PrerenderContents gets destroyed. Attaches the |final_status|
   // to the most recent prefetch matching the |url|.
   void SetPrefetchFinalStatusForUrl(const GURL& url, FinalStatus final_status);
diff --git a/chrome/browser/prerender/prerender_origin.h b/chrome/browser/prerender/prerender_origin.h
index 5ff992e..78fa21e 100644
--- a/chrome/browser/prerender/prerender_origin.h
+++ b/chrome/browser/prerender/prerender_origin.h
@@ -9,6 +9,11 @@
 
 // Origin indicates what caused the prerender.
 // NOTE: New values need to be appended, since they are used in histograms.
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. The values should remain
+// synchronized with the enum PrerenderOrigin in
+// //tools/metrics/histograms/enums.xml.
 enum Origin {
   // Obsolete: ORIGIN_LINK_REL_PRERENDER = 0,
   // Obsolete: ORIGIN_OMNIBOX_ORIGINAL = 1,
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc
index f5945a6..54b2dc1 100644
--- a/chrome/browser/prerender/prerender_unittest.cc
+++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -460,6 +460,12 @@
 }
 
 TEST_F(PrerenderTest, FoundTest) {
+  base::TimeDelta prefetch_age;
+  FinalStatus final_status;
+  Origin origin;
+
+  prerender_manager()->SetTickClockForTesting(tick_clock());
+
   GURL url("http://www.google.com/");
   DummyPrerenderContents* prerender_contents =
       prerender_manager()->CreateNextPrerenderContents(
@@ -470,6 +476,23 @@
   std::unique_ptr<PrerenderContents> entry =
       prerender_manager()->FindAndUseEntry(url);
   ASSERT_EQ(prerender_contents, entry.get());
+
+  EXPECT_TRUE(prerender_manager()->GetPrefetchInformation(
+      url, &prefetch_age, &final_status, &origin));
+  EXPECT_EQ(prerender::FINAL_STATUS_MAX, final_status);
+  EXPECT_EQ(prerender::ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, origin);
+
+  const base::TimeDelta advance_duration = TimeDelta::FromSeconds(1);
+  tick_clock()->Advance(advance_duration);
+  EXPECT_TRUE(prerender_manager()->GetPrefetchInformation(
+      url, &prefetch_age, &final_status, &origin));
+  EXPECT_LE(advance_duration, prefetch_age);
+  EXPECT_EQ(prerender::FINAL_STATUS_MAX, final_status);
+  EXPECT_EQ(prerender::ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, origin);
+
+  prerender_manager()->ClearPrefetchInformationForTesting();
+  EXPECT_FALSE(prerender_manager()->GetPrefetchInformation(
+      url, &prefetch_age, &final_status, &origin));
 }
 
 // Make sure that if queue a request, and a second prerender request for the
@@ -1510,6 +1533,10 @@
 // should be blocked by max_concurrency; abandons both of them and waits to make
 // sure both are cleared from the PrerenderLinkManager.
 TEST_F(PrerenderTest, LinkManagerClearOnPendingAbandon) {
+  base::TimeDelta prefetch_age;
+  FinalStatus final_status;
+  Origin origin;
+
   prerender_manager()->SetTickClockForTesting(tick_clock());
   SetConcurrency(1);
   ASSERT_LT(prerender_manager()->config().abandon_time_to_live,
@@ -1542,11 +1569,32 @@
   prerender_link_manager()->OnAbandonPrerender(kDefaultChildId,
                                                second_prerender_id);
 
-  tick_clock()->Advance(prerender_manager()->config().abandon_time_to_live +
-                        TimeDelta::FromSeconds(1));
+  EXPECT_TRUE(prerender_manager()->GetPrefetchInformation(
+      first_url, &prefetch_age, &final_status, &origin));
+  EXPECT_EQ(base::TimeDelta(), prefetch_age);
+  EXPECT_EQ(prerender::FINAL_STATUS_MAX, final_status);
+  EXPECT_EQ(prerender::ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, origin);
+
+  const base::TimeDelta advance_duration =
+      prerender_manager()->config().abandon_time_to_live +
+      TimeDelta::FromSeconds(1);
+  tick_clock()->Advance(advance_duration);
   EXPECT_FALSE(prerender_manager()->FindEntry(first_url));
   EXPECT_FALSE(prerender_manager()->FindEntry(pending_url));
   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
+
+  EXPECT_TRUE(prerender_manager()->GetPrefetchInformation(
+      first_url, &prefetch_age, &final_status, &origin));
+  EXPECT_EQ(advance_duration, prefetch_age);
+  EXPECT_EQ(prerender::FINAL_STATUS_TIMED_OUT, final_status);
+  EXPECT_EQ(prerender::ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, origin);
+
+  EXPECT_FALSE(prerender_manager()->GetPrefetchInformation(
+      pending_url, &prefetch_age, &final_status, &origin));
+
+  EXPECT_FALSE(prerender_manager()->GetPrefetchInformation(
+      GURL("https://not-prefetched.com/"), &prefetch_age, &final_status,
+      &origin));
 }
 
 // Creates two prerenders, one of which should be blocked by the
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 35b1584..bf6fcd0 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -35,7 +35,6 @@
 #include "chrome/browser/net/chrome_network_delegate.h"
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/net/profile_network_context_service_factory.h"
-#include "chrome/browser/net/quota_policy_channel_id_store.h"
 #include "chrome/browser/net/reporting_permissions_checker.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_constants.h"
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index d66a0216..2583c010 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -115,6 +115,11 @@
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
 #endif
 
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+#include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h"
+#include "components/offline_pages/core/prefetch/prefetch_service.h"
+#endif
+
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/metrics/android_profile_session_durations_service_factory.h"
 #include "chrome/browser/ntp_snippets/content_suggestions_notifier_service_factory.h"
@@ -1316,6 +1321,15 @@
   }
 
 #endif
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+  // Make sure to precreate the PrefetchGCMHandler before GCMProfileService is
+  // created, otherwise leads to infinite recursion
+  offline_pages::PrefetchService* prefetch_service =
+      offline_pages::PrefetchServiceFactory::GetForBrowserContext(profile);
+  if (prefetch_service != nullptr) {
+    prefetch_service->GetOrCreatePrefetchGCMHandler(profile);
+  }
+#endif
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
   // Initialization needs to happen after extension system initialization (for
   // extension::ManagementPolicy) and InitProfileUserPrefs (for setting the
diff --git a/chrome/browser/resources/chromeos/login/apps_menu.css b/chrome/browser/resources/chromeos/login/apps_menu.css
new file mode 100644
index 0000000..86ce3ba
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/apps_menu.css
@@ -0,0 +1,12 @@
+/* Copyright 2013 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. */
+
+.apps-menu-item {
+  background: no-repeat 4px 50%;
+  background-size: 16px;
+  overflow: hidden;
+  padding-inline-start: 24px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
diff --git a/chrome/browser/resources/chromeos/login/md_login.html b/chrome/browser/resources/chromeos/login/md_login.html
index a9b058a..8154b02e 100644
--- a/chrome/browser/resources/chromeos/login/md_login.html
+++ b/chrome/browser/resources/chromeos/login/md_login.html
@@ -11,9 +11,15 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/pin_keyboard.html">
+<link rel="stylesheet" href="chrome://resources/css/butter_bar.css">
 <link rel="stylesheet" href="chrome://resources/css/dialogs.css">
+<link rel="stylesheet" href="chrome://resources/css/list.css">
+<link rel="stylesheet" href="chrome://resources/css/menu_button.css">
+<link rel="stylesheet" href="chrome://resources/css/menu.css">
 <link rel="stylesheet" href="chrome://resources/css/spinner.css">
 <link rel="stylesheet" href="chrome://resources/css/throbber.css">
+<link rel="stylesheet" href="chrome://resources/css/widgets.css">
+<link rel="stylesheet" href="apps_menu.css">
 <link rel="stylesheet" href="../../../../../ui/login/bubble.css">
 <link rel="stylesheet" href="md_top_header_bar.css">
 <link rel="stylesheet" href="../../../../../ui/login/oobe.css">
@@ -26,7 +32,19 @@
 <script src="chrome://resources/js/event_tracker.js"></script>
 <script src="chrome://resources/js/cr/event_target.js"></script>
 <script src="chrome://resources/js/cr/ui.js"></script>
+<script src="chrome://resources/js/cr/ui/touch_handler.js"></script>
+<script src="chrome://resources/js/cr/ui/array_data_model.js"></script>
 <script src="chrome://resources/js/cr/ui/dialogs.js"></script>
+<script src="chrome://resources/js/cr/ui/list_selection_controller.js"></script>
+<script src="chrome://resources/js/cr/ui/list_selection_model.js"></script>
+<script src="chrome://resources/js/cr/ui/list_single_selection_model.js"></script>
+<script src="chrome://resources/js/cr/ui/list_item.js"></script>
+<script src="chrome://resources/js/cr/ui/list.js"></script>
+<script src="chrome://resources/js/cr/ui/grid.js"></script>
+<script src="chrome://resources/js/cr/ui/position_util.js"></script>
+<script src="chrome://resources/js/cr/ui/menu_item.js"></script>
+<script src="chrome://resources/js/cr/ui/menu.js"></script>
+<script src="chrome://resources/js/cr/ui/menu_button.js"></script>
 <script src="chrome://resources/js/load_time_data.js"></script>
 <script src="chrome://resources/js/promise_resolver.js"></script>
 <script src="chrome://resources/js/util.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/oobe.html b/chrome/browser/resources/chromeos/login/oobe.html
index ac3c843..8ef0b36 100644
--- a/chrome/browser/resources/chromeos/login/oobe.html
+++ b/chrome/browser/resources/chromeos/login/oobe.html
@@ -12,10 +12,16 @@
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/pin_keyboard.html">
 
+<link rel="stylesheet" href="chrome://resources/css/butter_bar.css">
 <link rel="stylesheet" href="chrome://resources/css/dialogs.css">
+<link rel="stylesheet" href="chrome://resources/css/list.css">
+<link rel="stylesheet" href="chrome://resources/css/menu_button.css">
+<link rel="stylesheet" href="chrome://resources/css/menu.css">
 <link rel="stylesheet" href="chrome://resources/css/spinner.css">
 <link rel="stylesheet" href="chrome://resources/css/throbber.css">
+<link rel="stylesheet" href="chrome://resources/css/widgets.css">
 
+<link rel="stylesheet" href="apps_menu.css">
 <link rel="stylesheet" href="../../../../../ui/login/bubble.css">
 <link rel="stylesheet" href="md_top_header_bar.css">
 <link rel="stylesheet" href="../../../../../ui/login/oobe.css">
@@ -30,7 +36,19 @@
 <script src="chrome://resources/js/event_tracker.js"></script>
 <script src="chrome://resources/js/cr/event_target.js"></script>
 <script src="chrome://resources/js/cr/ui.js"></script>
+<script src="chrome://resources/js/cr/ui/touch_handler.js"></script>
+<script src="chrome://resources/js/cr/ui/array_data_model.js"></script>
 <script src="chrome://resources/js/cr/ui/dialogs.js"></script>
+<script src="chrome://resources/js/cr/ui/list_selection_controller.js"></script>
+<script src="chrome://resources/js/cr/ui/list_selection_model.js"></script>
+<script src="chrome://resources/js/cr/ui/list_single_selection_model.js"></script>
+<script src="chrome://resources/js/cr/ui/list_item.js"></script>
+<script src="chrome://resources/js/cr/ui/list.js"></script>
+<script src="chrome://resources/js/cr/ui/grid.js"></script>
+<script src="chrome://resources/js/cr/ui/position_util.js"></script>
+<script src="chrome://resources/js/cr/ui/menu_item.js"></script>
+<script src="chrome://resources/js/cr/ui/menu.js"></script>
+<script src="chrome://resources/js/cr/ui/menu_button.js"></script>
 <script src="chrome://resources/js/load_time_data.js"></script>
 <script src="chrome://resources/js/promise_resolver.js"></script>
 <script src="chrome://resources/js/util.js"></script>
@@ -65,6 +83,7 @@
 
 <script src="chrome://oobe/keyboard_utils.js"></script>
 
+<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://oobe/custom_elements.html">
 <script src="chrome://oobe/oobe.js"></script>
 </head>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html
index 6c65e6b..0e746229 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -64,6 +64,7 @@
         on-accessibility-button-clicked="onWelcomeAccessibilityButtonClicked_"
         on-timezone-button-clicked="onWelcomeTimezoneButtonClicked_"
         on-next-button-clicked="onWelcomeNextButtonClicked_"
+        on-enable-debugging-clicked="onEnableDebuggingClicked_"
         on-launch-advanced-options="onWelcomeLaunchAdvancedOptions_"
         timezone-button-visible=
             "[[isTimezoneButtonVisible_(highlightStrength)]]"
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js
index a9d0de6..a394b6e 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -260,6 +260,15 @@
   },
 
   /**
+   * Handles "enable-debugging" link for "Welcome" screen.
+   *
+   * @private
+   */
+  onEnableDebuggingClicked_: function() {
+    cr.ui.Oobe.handleAccelerator(ACCELERATOR_ENABLE_DEBBUGING);
+  },
+
+  /**
    * Handle "launch-advanced-options" button for "Welcome" screen.
    *
    * @private
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
index 804c5403..66abc083 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
@@ -112,7 +112,7 @@
           </if>
         </div>
         <div hidden="[[!debuggingLinkVisible]]">
-          <a href="#" on-tap="onDebuggingLinkClicked_">
+          <a href="#" on-tap="onDebuggingLinkClicked_" id="enableDebuggingLink">
             [[i18nDynamic(locale, 'debuggingFeaturesLink')]]
           </a>
         </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
index 4926033..052f6a6 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
@@ -351,8 +351,7 @@
     },
 
     onDebuggingLinkClicked_: function() {
-      chrome.send(
-          'login.WelcomeScreen.userActed', ['connect-debugging-features']);
+      this.fire('enable-debugging-clicked');
     },
 
     /*
diff --git a/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
index 4d608e4..1bc9016 100644
--- a/chrome/browser/resources/safe_browsing/download_file_types.asciipb
+++ b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -8,7 +8,7 @@
 ##
 ## Top level settings
 ##
-version_id: 32
+version_id: 33
 sampled_ping_probability: 0.01
 max_archived_binaries_to_report: 10
 default_file_type {
@@ -705,6 +705,9 @@
   is_archive: true
   ping_setting: FULL_PING
   inspection_type: ZIP
+  platform_settings {
+    max_file_size_to_analyze: 52428800 # 50MB
+  }
 }
 file_types {
   extension: "zipx"
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js
index 025e9262..14c3b80 100644
--- a/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -107,7 +107,10 @@
       // <if expr="chromeos">
       controlledSettingShared:
           loadTimeData.getString('controlledSettingShared'),
-      controlledSettingOwner: loadTimeData.getString('controlledSettingOwner'),
+      controlledSettingWithOwner:
+          loadTimeData.getString('controlledSettingWithOwner'),
+      controlledSettingNoOwner:
+          loadTimeData.getString('controlledSettingNoOwner'),
       // </if>
     };
 
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc
index 53e35a2..256ec83 100644
--- a/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc
@@ -877,4 +877,47 @@
   EXPECT_EQ(1, result_.directory_count);
 }
 
+TEST_F(FileAnalyzerTest, LargeZipSkipsContentInspection) {
+  scoped_refptr<MockBinaryFeatureExtractor> extractor =
+      new testing::StrictMock<MockBinaryFeatureExtractor>();
+  FileAnalyzer analyzer(extractor);
+  base::RunLoop run_loop;
+
+  FileTypePoliciesTestOverlay overlay;
+  std::unique_ptr<DownloadFileTypeConfig> config = overlay.DuplicateConfig();
+  for (DownloadFileType& file_type : *config->mutable_file_types()) {
+    if (file_type.extension() == "zip") {
+      // All archives will skip content inspection.
+      file_type.mutable_platform_settings(0)->set_max_file_size_to_analyze(0);
+      break;
+    }
+  }
+  overlay.SwapConfig(config);
+
+  base::FilePath target_path(FILE_PATH_LITERAL("target.zip"));
+  base::FilePath tmp_path =
+      temp_dir_.GetPath().Append(FILE_PATH_LITERAL("tmp.crdownload"));
+
+  base::ScopedTempDir zip_source_dir;
+  ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir());
+  std::string file_contents = "dummy file";
+  ASSERT_EQ(static_cast<int>(file_contents.size()),
+            base::WriteFile(
+                zip_source_dir.GetPath().Append(FILE_PATH_LITERAL("file.exe")),
+                file_contents.data(), file_contents.size()));
+  ASSERT_TRUE(zip::Zip(zip_source_dir.GetPath(), tmp_path,
+                       /* include_hidden_files= */ false));
+
+  analyzer.Start(
+      target_path, tmp_path,
+      base::BindOnce(&FileAnalyzerTest::DoneCallback, base::Unretained(this),
+                     run_loop.QuitClosure()));
+  run_loop.Run();
+
+  ASSERT_TRUE(has_result_);
+  EXPECT_EQ(result_.type, ClientDownloadRequest::ZIPPED_EXECUTABLE);
+  EXPECT_EQ(result_.archive_is_valid, FileAnalyzer::ArchiveValid::VALID);
+  ASSERT_EQ(0, result_.archived_binaries.size());
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/secure_origin_whitelist_browsertest.cc b/chrome/browser/secure_origin_whitelist_browsertest.cc
index 150294bb..fc04f66 100644
--- a/chrome/browser/secure_origin_whitelist_browsertest.cc
+++ b/chrome/browser/secure_origin_whitelist_browsertest.cc
@@ -17,6 +17,7 @@
 #include "components/security_state/core/features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
+#include "services/network/public/cpp/network_switches.h"
 
 namespace {
 // SecureOriginWhitelistBrowsertests differ in the setup of the browser. Since
@@ -58,7 +59,7 @@
       return;
 
     command_line->AppendSwitchASCII(
-        switches::kUnsafelyTreatInsecureOriginAsSecure, BaseURL());
+        network::switches::kUnsafelyTreatInsecureOriginAsSecure, BaseURL());
   }
 
   void SetUpInProcessBrowserTestFixture() override {
diff --git a/chrome/browser/ssl/origin_util.cc b/chrome/browser/ssl/origin_util.cc
index 0c975da..1ec4424 100644
--- a/chrome/browser/ssl/origin_util.cc
+++ b/chrome/browser/ssl/origin_util.cc
@@ -9,37 +9,29 @@
 
 #include "base/strings/pattern.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/secure_origin_whitelist.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/common/origin_util.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "url/gurl.h"
 
 namespace {
 
-// Returns a vector containing all origins and patterns whitelisted as "Secure"
+// Returns a vector containing all origins and patterns allowlisted as "Secure"
 // by the OverrideSecurityRestrictionsOnInsecureOrigin policy.
 std::vector<std::string> GetSecureOriginsAndPatterns(PrefService* prefs) {
   if (prefs->HasPrefPath(prefs::kUnsafelyTreatInsecureOriginAsSecure)) {
-    return secure_origin_whitelist::ParseWhitelist(
+    return network::ParseSecureOriginAllowlist(
         prefs->GetString(prefs::kUnsafelyTreatInsecureOriginAsSecure));
   }
   return std::vector<std::string>();
 }
 
-// Returns true if |origin| matches an origin or pattern in the whitelist from
+// Returns true if |origin| matches an origin or pattern in the allowlist from
 // the OverrideSecurityRestrictionsOnInsecureOrigin policy.
 bool IsPolicyWhitelistedAsSecureOrigin(const url::Origin& origin,
                                        PrefService* prefs) {
-  std::vector<std::string> whitelist = GetSecureOriginsAndPatterns(prefs);
-  if (base::ContainsValue(whitelist, origin.Serialize())) {
-    return true;
-  }
-  for (const auto& origin_or_pattern : whitelist) {
-    if (base::MatchPattern(origin.host(), origin_or_pattern)) {
-      return true;
-    }
-  }
-  return false;
+  std::vector<std::string> allowlist = GetSecureOriginsAndPatterns(prefs);
+  return network::IsAllowlistedAsSecureOrigin(origin, allowlist);
 }
 
 }  // namespace
diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc
index 0066398..1ca339c 100644
--- a/chrome/browser/ssl/security_state_tab_helper.cc
+++ b/chrome/browser/ssl/security_state_tab_helper.cc
@@ -34,6 +34,8 @@
 #include "net/cert/x509_certificate.h"
 #include "net/ssl/ssl_cipher_suite_names.h"
 #include "net/ssl/ssl_connection_status_flags.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/network/public/cpp/network_switches.h"
 #include "third_party/boringssl/src/include/openssl/ssl.h"
 #include "url/origin.h"
 
@@ -287,13 +289,14 @@
       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
   PrefService* prefs = profile->GetPrefs();
   std::string origins_str = "";
-  if (command_line.HasSwitch(switches::kUnsafelyTreatInsecureOriginAsSecure)) {
+  if (command_line.HasSwitch(
+          network::switches::kUnsafelyTreatInsecureOriginAsSecure)) {
     origins_str = command_line.GetSwitchValueASCII(
-        switches::kUnsafelyTreatInsecureOriginAsSecure);
+        network::switches::kUnsafelyTreatInsecureOriginAsSecure);
   } else if (prefs->HasPrefPath(prefs::kUnsafelyTreatInsecureOriginAsSecure)) {
     origins_str = prefs->GetString(prefs::kUnsafelyTreatInsecureOriginAsSecure);
   }
-  return secure_origin_whitelist::ParseWhitelist(origins_str);
+  return network::ParseSecureOriginAllowlist(origins_str);
 }
 
 WEB_CONTENTS_USER_DATA_KEY_IMPL(SecurityStateTabHelper)
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index fc6a58f..115ba79 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -22,6 +22,7 @@
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/autofill_switches.h"
@@ -65,6 +66,7 @@
 
 const char kLocalGuidA[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44A";
 const char kDifferentBillingAddressId[] = "another address entity ID";
+const base::Time kArbitraryDefaultTime = base::Time::FromDoubleT(25);
 
 template <class T>
 class AutofillWebDataServiceConsumer : public WebDataServiceConsumer {
@@ -188,7 +190,10 @@
 
 class SingleClientWalletSyncTest : public SyncTest {
  public:
-  SingleClientWalletSyncTest() : SyncTest(SINGLE_CLIENT) {}
+  SingleClientWalletSyncTest() : SyncTest(SINGLE_CLIENT) {
+    test_clock_.SetNow(kArbitraryDefaultTime);
+  }
+
   ~SingleClientWalletSyncTest() override {}
 
  protected:
@@ -256,8 +261,13 @@
                                        0);
   }
 
+  void AdvanceAutofillClockByOneDay() {
+    test_clock_.Advance(base::TimeDelta::FromDays(1));
+  }
+
   PersonalDataLoadedObserverMock personal_data_observer_;
   base::HistogramTester histogram_tester_;
+  autofill::TestAutofillClock test_clock_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SingleClientWalletSyncTest);
@@ -841,6 +851,61 @@
   ExpectAddressesDiffInHistograms(/*added=*/0, /*removed=*/0);
 }
 
+// Tests that we do report age metric on startup.
+IN_PROC_BROWSER_TEST_P(SingleClientWalletSyncTestWithDefaultFeatures,
+                       PRE_UseDateMetricReportedOnStartup) {
+  GetFakeServer()->SetWalletData(
+      {CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
+                            kDefaultBillingAddressID),
+       CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
+       CreateDefaultSyncPaymentsCustomerData()});
+  ASSERT_TRUE(SetupSync());
+
+  // Make sure the data is present on the client.
+  autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+
+  // Here, we would ideally test that no metrics get recorded during initial
+  // sync. Due to design differences between USS&Directory, we cannot make it
+  // work (the metadata syncable service has no reliable way to tell it is
+  // initial sync).
+}
+
+IN_PROC_BROWSER_TEST_P(SingleClientWalletSyncTestWithDefaultFeatures,
+                       UseDateMetricReportedOnStartup) {
+  // Advance the clock to get a reasonable value.
+  AdvanceAutofillClockByOneDay();
+
+  // Set the same data on the server so that we get an empty update (this is
+  // based on a hash of the data).
+  GetFakeServer()->SetWalletData(
+      {CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
+                            kDefaultBillingAddressID),
+       CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
+       CreateDefaultSyncPaymentsCustomerData()});
+  ASSERT_TRUE(SetupSync());
+
+  // Make sure the data is still present on the client.
+  autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+
+  // The metric gets recorded.
+  histogram_tester_.ExpectTotalCount("Autofill.WalletUseDate.Card", 1);
+  histogram_tester_.ExpectTimeBucketCount(
+      "Autofill.WalletUseDate.Card",
+      /*sample=*/base::TimeDelta::FromDays(1),
+      /*count=*/1);
+  histogram_tester_.ExpectTotalCount("Autofill.WalletUseDate.Address", 1);
+  histogram_tester_.ExpectTimeBucketCount(
+      "Autofill.WalletUseDate.Address",
+      /*sample=*/base::TimeDelta::FromDays(1),
+      /*count=*/1);
+}
+
 // Wallet data should get cleared from the database when the wallet sync type
 // flag is disabled.
 IN_PROC_BROWSER_TEST_P(SingleClientWalletSyncTestWithDefaultFeatures,
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc
index 33125db..b8e5e35 100644
--- a/chrome/browser/ui/startup/bad_flags_prompt.cc
+++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/startup/bad_flags_prompt.h"
 
+#include <string>
+
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
@@ -97,7 +99,7 @@
 
     // This flag allows people to whitelist certain origins as secure, even
     // if they are not.
-    switches::kUnsafelyTreatInsecureOriginAsSecure,
+    network::switches::kUnsafelyTreatInsecureOriginAsSecure,
 
     // This flag allows sites to access the camera and microphone without
     // getting the user's permission.
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
index 8c1e486..c461815 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -242,6 +242,7 @@
 void ImmersiveModeControllerAsh::OnImmersiveRevealEnded() {
   UninstallEventRewriter();
   visible_fraction_ = 0;
+  browser_view_->contents_web_view()->holder()->SetHitTestTopInset(0);
   for (Observer& observer : observers_)
     observer.OnImmersiveRevealEnded();
 }
@@ -250,6 +251,7 @@
 
 void ImmersiveModeControllerAsh::OnImmersiveFullscreenExited() {
   UninstallEventRewriter();
+  browser_view_->contents_web_view()->holder()->SetHitTestTopInset(0);
   for (Observer& observer : observers_)
     observer.OnImmersiveFullscreenExited();
 }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
index e29c1bc..6127fd2b0 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "ui/aura/window.h"
 #include "ui/events/event.h"
+#include "ui/views/controls/native/native_view_host.h"
 #include "ui/views/controls/webview/webview.h"
 
 class ImmersiveModeControllerAshTest : public TestWithBrowserView {
@@ -128,6 +129,8 @@
   // By default, the tabstrip and toolbar should be visible.
   EXPECT_TRUE(tabstrip->visible());
   EXPECT_TRUE(toolbar->visible());
+  EXPECT_EQ(
+      0, browser_view()->contents_web_view()->holder()->GetHitTestTopInset());
 
   ToggleFullscreen();
   EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen());
@@ -139,6 +142,8 @@
   // Tabstrip and top container view should be completely offscreen.
   EXPECT_EQ(0, GetBoundsInWidget(tabstrip).bottom());
   EXPECT_EQ(0, GetBoundsInWidget(browser_view()->top_container()).bottom());
+  EXPECT_EQ(
+      0, browser_view()->contents_web_view()->holder()->GetHitTestTopInset());
 
   // Since the tab strip and tool bar are both hidden in immersive fullscreen
   // mode, the web contents should extend to the edge of screen.
@@ -150,6 +155,8 @@
   EXPECT_TRUE(controller()->IsRevealed());
   EXPECT_TRUE(tabstrip->visible());
   EXPECT_TRUE(toolbar->visible());
+  EXPECT_NE(
+      0, browser_view()->contents_web_view()->holder()->GetHitTestTopInset());
 
   // The TopContainerView should be flush with the top edge of the widget. If
   // it is not flush with the top edge the immersive reveal animation looks
@@ -189,6 +196,8 @@
   // Exiting both immersive and tab fullscreen should show the tab strip and
   // toolbar.
   ToggleFullscreen();
+  EXPECT_EQ(
+      0, browser_view()->contents_web_view()->holder()->GetHitTestTopInset());
   EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen());
   EXPECT_FALSE(controller()->IsEnabled());
   EXPECT_FALSE(controller()->IsRevealed());
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
index 837e33e7..58bef1e6 100644
--- a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -17,6 +17,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "services/network/public/cpp/network_switches.h"
 
 namespace {
 
@@ -46,7 +47,7 @@
     InProcessBrowserTest::SetUpCommandLine(command_line);
 
     command_line->AppendSwitchASCII(
-        switches::kUnsafelyTreatInsecureOriginAsSecure,
+        network::switches::kUnsafelyTreatInsecureOriginAsSecure,
         GetInstallableAppURL().GetOrigin().spec());
   }
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index 9e5dac52..a9aaf0b 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -26,6 +27,7 @@
 #include "ui/gfx/color_utils.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_highlight.h"
+#include "ui/views/animation/installable_ink_drop.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/controls/menu/menu_item_view.h"
@@ -48,6 +50,10 @@
       show_menu_factory_(this) {
   set_has_ink_drop_action_on_click(true);
   set_context_menu_controller(this);
+
+  if (base::FeatureList::IsEnabled(views::kInstallableInkDropFeature))
+    installable_ink_drop_ = std::make_unique<views::InstallableInkDrop>();
+
   SetInkDropMode(InkDropMode::ON);
 
   // Make sure icons are flipped by default so that back, forward, etc. follows
@@ -246,17 +252,33 @@
     node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kPress);
 }
 
+std::unique_ptr<views::InkDrop> ToolbarButton::CreateInkDrop() {
+  // Ensure this doesn't get called when InstallableInkDrops are enabled.
+  DCHECK(!base::FeatureList::IsEnabled(views::kInstallableInkDropFeature));
+  return views::LabelButton::CreateInkDrop();
+}
+
 std::unique_ptr<views::InkDropHighlight> ToolbarButton::CreateInkDropHighlight()
     const {
+  // Ensure this doesn't get called when InstallableInkDrops are enabled.
+  DCHECK(!base::FeatureList::IsEnabled(views::kInstallableInkDropFeature));
   return CreateToolbarInkDropHighlight(this);
 }
 
 SkColor ToolbarButton::GetInkDropBaseColor() const {
+  // Ensure this doesn't get called when InstallableInkDrops are enabled.
+  DCHECK(!base::FeatureList::IsEnabled(views::kInstallableInkDropFeature));
   if (highlight_color_)
     return *highlight_color_;
   return GetToolbarInkDropBaseColor(this);
 }
 
+views::InkDrop* ToolbarButton::GetInkDrop() {
+  if (installable_ink_drop_)
+    return installable_ink_drop_.get();
+  return views::LabelButton::GetInkDrop();
+}
+
 void ToolbarButton::ShowContextMenuForViewImpl(View* source,
                                                const gfx::Point& point,
                                                ui::MenuSourceType source_type) {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
index b54a6a0..b86afc3 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -26,6 +26,7 @@
 }
 
 namespace views {
+class InstallableInkDrop;
 class MenuModelAdapter;
 class MenuRunner;
 }
@@ -79,8 +80,10 @@
   void OnMouseExited(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+  std::unique_ptr<views::InkDrop> CreateInkDrop() override;
   std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
       const override;
+  views::InkDrop* GetInkDrop() override;
   SkColor GetInkDropBaseColor() const override;
 
   // views::ContextMenuController:
@@ -157,6 +160,10 @@
   // default ToolbarButton ink drop.
   base::Optional<SkColor> highlight_color_;
 
+  // Used instead of the standard InkDrop implementation when
+  // |views::kInstallableInkDropFeature| is enabled.
+  std::unique_ptr<views::InstallableInkDrop> installable_ink_drop_;
+
   // A factory for tasks that show the dropdown context menu for the button.
   base::WeakPtrFactory<ToolbarButton> show_menu_factory_;
 
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
index 4316919..2418c18 100644
--- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
@@ -265,7 +265,6 @@
           ProfileManager::GetActiveUserProfile());
   connector->BindInterface(assistant::mojom::kServiceName,
                            mojo::MakeRequest(&settings_manager_));
-  client_binding_.Bind(mojo::MakeRequest(&client_ptr_));
 
   if (initialized_) {
     SendGetSettingsRequest();
@@ -458,8 +457,11 @@
     if (!prefs->GetBoolean(arc::prefs::kVoiceInteractionHotwordEnabled)) {
       prefs->SetBoolean(arc::prefs::kVoiceInteractionHotwordEnabled, true);
     }
+
+    assistant::mojom::SpeakerIdEnrollmentClientPtr client_ptr;
+    client_binding_.Bind(mojo::MakeRequest(&client_ptr));
     settings_manager_->StartSpeakerIdEnrollment(is_retrain_flow_,
-                                                std::move(client_ptr_));
+                                                std::move(client_ptr));
   }
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
index bbfedcd..3b9bf0e 100644
--- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
@@ -133,7 +133,6 @@
   bool initialized_ = false;
 
   mojo::Binding<assistant::mojom::SpeakerIdEnrollmentClient> client_binding_;
-  assistant::mojom::SpeakerIdEnrollmentClientPtr client_ptr_;
   assistant::mojom::AssistantSettingsManagerPtr settings_manager_;
   base::WeakPtrFactory<AssistantOptInFlowScreenHandler> weak_factory_;
 
diff --git a/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc b/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
index e7e5f6e..cf11f3c0 100644
--- a/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
@@ -32,7 +32,8 @@
      IDS_CONTROLLED_SETTING_EXTENSION_WITHOUT_NAME},
 #if defined(OS_CHROMEOS)
     {"controlledSettingShared", IDS_CONTROLLED_SETTING_SHARED},
-    {"controlledSettingOwner", IDS_CONTROLLED_SETTING_OWNER},
+    {"controlledSettingWithOwner", IDS_CONTROLLED_SETTING_WITH_OWNER},
+    {"controlledSettingNoOwner", IDS_CONTROLLED_SETTING_NO_OWNER},
 #endif
   };
   AddLocalizedStringsBulk(html_source, localized_strings,
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index d3b62651..75bf966 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -126,6 +126,8 @@
     "component_flash_hint_file_linux.h",
     "conflicts/module_watcher_win.cc",
     "conflicts/module_watcher_win.h",
+    "conflicts/remote_module_watcher_win.cc",
+    "conflicts/remote_module_watcher_win.h",
     "content_restriction.h",
     "crash_keys.cc",
     "crash_keys.h",
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 45f0aa9..40668377 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -34,7 +34,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/common/pepper_flash.h"
-#include "chrome/common/secure_origin_whitelist.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/common_resources.h"
 #include "components/crash/core/common/crash_key.h"
@@ -625,8 +624,6 @@
   // with them by third parties.
   schemes->secure_schemes.push_back(extensions::kExtensionScheme);
 
-  schemes->secure_origins = secure_origin_whitelist::GetWhitelist();
-
   // chrome-native: is a scheme used for placeholder navigations that allow
   // UIs to be drawn with platform native widgets instead of HTML.  These pages
   // should be treated as empty documents that can commit synchronously.
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index a3d7829..f7852fa 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -634,15 +634,6 @@
 // apps/origins.  This should be used only for testing purpose.
 const char kUnlimitedStorage[]              = "unlimited-storage";
 
-// Treat given (insecure) origins as secure origins. Multiple origins can be
-// supplied as a comma-separated list. For the definition of secure contexts,
-// see https://w3c.github.io/webappsec-secure-contexts/
-//
-// Example:
-// --unsafely-treat-insecure-origin-as-secure=http://a.test,http://b.test
-const char kUnsafelyTreatInsecureOriginAsSecure[] =
-    "unsafely-treat-insecure-origin-as-secure";
-
 // Pass the full https:// URL to PAC (Proxy Auto Config) scripts. As opposed to
 // the default behavior which strips path and query components before passing
 // to the PAC scripts.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index dc3f4b6..04db70f 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -187,7 +187,6 @@
 extern const char kTrustedDownloadSources[];
 extern const char kTryChromeAgain[];
 extern const char kUnlimitedStorage[];
-extern const char kUnsafelyTreatInsecureOriginAsSecure[];
 extern const char kUnsafePacUrl[];
 extern const char kUserAgent[];
 extern const char kUserDataDir[];
diff --git a/chrome/common/conflicts/remote_module_watcher_win.cc b/chrome/common/conflicts/remote_module_watcher_win.cc
new file mode 100644
index 0000000..ce00b786
--- /dev/null
+++ b/chrome/common/conflicts/remote_module_watcher_win.cc
@@ -0,0 +1,70 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/conflicts/remote_module_watcher_win.h"
+
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "content/public/common/service_names.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace {
+
+// Note: Can be called on any threads, even those not owned by the task
+//       scheduler.
+void OnModuleEvent(
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    const ModuleWatcher::OnModuleEventCallback& on_module_event_callback,
+    const ModuleWatcher::ModuleEvent& event) {
+  task_runner->PostTask(FROM_HERE,
+                        base::BindOnce(on_module_event_callback, event));
+}
+
+}  // namespace
+
+RemoteModuleWatcher::~RemoteModuleWatcher() = default;
+
+// static
+RemoteModuleWatcher::UniquePtr RemoteModuleWatcher::Create(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    service_manager::Connector* connector) {
+  auto remote_module_watcher =
+      UniquePtr(new RemoteModuleWatcher(task_runner),
+                base::OnTaskRunnerDeleter(task_runner));
+
+  // Because |remote_module_watcher| will be sent for deletion on |task_runner|,
+  // using an unretained pointer to it is safe as the initialization is
+  // guaranteed to be run before the destructor.
+  task_runner->PostTask(
+      FROM_HERE, base::BindOnce(&RemoteModuleWatcher::InitializeOnTaskRunner,
+                                base::Unretained(remote_module_watcher.get()),
+                                connector->Clone()));
+
+  return remote_module_watcher;
+}
+
+RemoteModuleWatcher::RemoteModuleWatcher(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+    : task_runner_(task_runner), weak_ptr_factory_(this) {}
+
+void RemoteModuleWatcher::InitializeOnTaskRunner(
+    std::unique_ptr<service_manager::Connector> connector) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  connector->BindInterface(content::mojom::kBrowserServiceName,
+                           &module_event_sink_);
+
+  module_watcher_ = ModuleWatcher::Create(base::BindRepeating(
+      &OnModuleEvent, task_runner_,
+      base::BindRepeating(&RemoteModuleWatcher::HandleModuleEvent,
+                          weak_ptr_factory_.GetWeakPtr())));
+}
+
+void RemoteModuleWatcher::HandleModuleEvent(
+    const ModuleWatcher::ModuleEvent& event) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  module_event_sink_->OnModuleEvent(
+      event.event_type, reinterpret_cast<uintptr_t>(event.module_load_address));
+}
diff --git a/chrome/common/conflicts/remote_module_watcher_win.h b/chrome/common/conflicts/remote_module_watcher_win.h
new file mode 100644
index 0000000..c0e716a
--- /dev/null
+++ b/chrome/common/conflicts/remote_module_watcher_win.h
@@ -0,0 +1,71 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_CONFLICTS_REMOTE_MODULE_WATCHER_WIN_H_
+#define CHROME_COMMON_CONFLICTS_REMOTE_MODULE_WATCHER_WIN_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/common/conflicts/module_event_sink_win.mojom.h"
+#include "chrome/common/conflicts/module_watcher_win.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+struct OnTaskRunnerDeleter;
+}  // namespace base
+
+namespace service_manager {
+class Connector;
+}
+
+// This class is used to instantiate a ModuleWatcher instance in a child
+// process that forwards all the module events to the browser process via the
+// mojom::ModuleEventSink interface.
+class RemoteModuleWatcher {
+ public:
+  // Provided for convenience.
+  using UniquePtr =
+      std::unique_ptr<RemoteModuleWatcher, base::OnTaskRunnerDeleter>;
+
+  ~RemoteModuleWatcher();
+
+  // Creates a RemoteModuleWatcher instance and initializes it on |task_runner|.
+  // The instance lives on that task runner and will be destroyed there when the
+  // UniquePtr is destroyed.
+  static UniquePtr Create(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      service_manager::Connector* connector);
+
+ private:
+  explicit RemoteModuleWatcher(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+  // Initializes this instance by connecting the |module_event_sink_| instance
+  // and starting the |module_watcher_|. Called on |task_runner_|.
+  void InitializeOnTaskRunner(
+      std::unique_ptr<service_manager::Connector> connector);
+
+  // Receives module load events from the |module_watcher_| and forwards them to
+  // the |module_event_sink_|.
+  void HandleModuleEvent(const ModuleWatcher::ModuleEvent& event);
+
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+  // Module events from |module_watcher_| are forwarded to the browser process
+  // through this sink.
+  mojo::InterfacePtr<mojom::ModuleEventSink> module_event_sink_;
+
+  // Observes module load events.
+  std::unique_ptr<ModuleWatcher> module_watcher_;
+
+  base::WeakPtrFactory<RemoteModuleWatcher> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteModuleWatcher);
+};
+
+#endif  // CHROME_COMMON_CONFLICTS_REMOTE_MODULE_WATCHER_WIN_H_
diff --git a/chrome/common/conflicts/remote_module_watcher_win_unittest.cc b/chrome/common/conflicts/remote_module_watcher_win_unittest.cc
new file mode 100644
index 0000000..a47fb68
--- /dev/null
+++ b/chrome/common/conflicts/remote_module_watcher_win_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/conflicts/remote_module_watcher_win.h"
+
+#include <windows.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/task/post_task.h"
+#include "base/test/scoped_task_environment.h"
+#include "chrome/common/conflicts/module_event_sink_win.mojom.h"
+#include "content/public/common/service_names.mojom.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/service_binding.h"
+#include "services/service_manager/public/cpp/test/test_connector_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class RemoteModuleWatcherTest : public testing::Test,
+                                public service_manager::Service,
+                                public mojom::ModuleEventSink {
+ public:
+  RemoteModuleWatcherTest()
+      : service_binding_(this,
+                         test_connector_factory_.RegisterInstance(
+                             content::mojom::kBrowserServiceName)),
+        binding_(this) {}
+
+  ~RemoteModuleWatcherTest() override = default;
+
+  // service_manager::Service:
+  void OnStart() override {
+    registry_.AddInterface(base::BindRepeating(
+        &RemoteModuleWatcherTest::BindModuleEventSinkRequest,
+        base::Unretained(this)));
+  }
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override {
+    registry_.BindInterface(interface_name, std::move(interface_pipe));
+  }
+
+  // mojom::ModuleEventSink:
+  void OnModuleEvent(mojom::ModuleEventType event_type,
+                     uint64_t load_address) override {
+    module_event_count_++;
+  }
+
+  // Returns a connector that may be used to connect to a ModuleEventSink implementation.
+  service_manager::Connector* GetConnector() {
+    return test_connector_factory_.GetDefaultConnector();
+  }
+
+  void LoadModule() {
+    if (module_handle_)
+      return;
+    // This module should not be a static dependency of the unit-test
+    // executable, but should be a build-system dependency or a module that is
+    // present on any Windows machine.
+    static constexpr wchar_t kModuleName[] = L"conflicts_dll.dll";
+    // The module should not already be loaded.
+    ASSERT_FALSE(::GetModuleHandle(kModuleName));
+    // It should load successfully.
+    module_handle_ = ::LoadLibrary(kModuleName);
+    ASSERT_TRUE(module_handle_);
+  }
+
+  void UnloadModule() {
+    if (!module_handle_)
+      return;
+    ::FreeLibrary(module_handle_);
+    module_handle_ = nullptr;
+  }
+
+  // Runs the task scheduler until no tasks are running.
+  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+
+  HMODULE module_handle() { return module_handle_; }
+
+  int module_event_count() { return module_event_count_; }
+
+ private:
+  void BindModuleEventSinkRequest(mojom::ModuleEventSinkRequest request) {
+    binding_.Bind(std::move(request));
+  }
+
+  // Must be first.
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  service_manager::TestConnectorFactory test_connector_factory_;
+
+  // Used to implement |service_manager::Service|.
+  service_manager::ServiceBinding service_binding_;
+  service_manager::BinderRegistry registry_;
+
+  // Binds a ModuleEventSinkRequest to this implementation of ModuleEventSink.
+  mojo::Binding<mojom::ModuleEventSink> binding_;
+
+  // Holds a handle to a loaded module.
+  HMODULE module_handle_ = nullptr;
+
+  // Total number of module events seen.
+  int module_event_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteModuleWatcherTest);
+};
+
+}  // namespace
+
+TEST_F(RemoteModuleWatcherTest, ModuleEvents) {
+  auto task_runner = base::CreateSingleThreadTaskRunnerWithTraits({});
+
+  auto remote_module_watcher =
+      RemoteModuleWatcher::Create(task_runner, GetConnector());
+
+  // Wait until the watcher is initialized and a few module events are received.
+  RunUntilIdle();
+  EXPECT_GT(module_event_count(), 0);
+
+  // Dynamically load a module and ensure a notification is received for it.
+  int previous_module_event_count = module_event_count();
+  LoadModule();
+  RunUntilIdle();
+  EXPECT_GT(module_event_count(), previous_module_event_count);
+
+  UnloadModule();
+
+  // Destroy the module watcher.
+  remote_module_watcher = nullptr;
+  RunUntilIdle();
+
+  // Load the module and ensure no notification is received this time.
+  previous_module_event_count = module_event_count();
+  LoadModule();
+  RunUntilIdle();
+
+  EXPECT_EQ(module_event_count(), previous_module_event_count);
+
+  UnloadModule();
+}
diff --git a/chrome/common/safe_browsing/zip_analyzer.cc b/chrome/common/safe_browsing/zip_analyzer.cc
index 773f8bb..f499222 100644
--- a/chrome/common/safe_browsing/zip_analyzer.cc
+++ b/chrome/common/safe_browsing/zip_analyzer.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/numerics/ranges.h"
 #include "base/rand_util.h"
 #include "build/build_config.h"
@@ -68,6 +69,16 @@
     return;
   }
 
+  bool too_big_to_unpack =
+      base::checked_cast<uint64_t>(zip_file.GetLength()) >
+      FileTypePolicies::GetInstance()->GetMaxFileSizeToAnalyze("zip");
+  UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipTooBigToUnpack",
+                        too_big_to_unpack);
+  if (too_big_to_unpack) {
+    results->success = true;
+    return;
+  }
+
   bool contains_zip = false;
   bool advanced = true;
   int zip_entry_count = 0;
diff --git a/chrome/common/secure_origin_whitelist.cc b/chrome/common/secure_origin_whitelist.cc
index b70d6ce..2f3d863 100644
--- a/chrome/common/secure_origin_whitelist.cc
+++ b/chrome/common/secure_origin_whitelist.cc
@@ -4,163 +4,15 @@
 
 #include "chrome/common/secure_origin_whitelist.h"
 
-#include "base/command_line.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "chrome/common/chrome_switches.h"
+#include <set>
+#include <string>
+
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "extensions/common/constants.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-#include "url/scheme_host_port.h"
-
-namespace {
-
-// Given a hostname pattern with a wildcard such as "*.foo.com", returns
-// true if |hostname_pattern| meets both of these conditions:
-// 1.) A string matching |hostname_pattern| is a valid hostname.
-// 2.) Wildcards only appear beyond the eTLD+1. "*.foo.com" is considered
-//     valid but "*.com" is not.
-bool IsValidWildcardPattern(const std::string& hostname_pattern) {
-  // Replace wildcards with dummy values to check whether a matching origin is
-  // valid.
-  std::string wildcards_replaced;
-  if (!base::ReplaceChars(hostname_pattern, "*", "a", &wildcards_replaced))
-    return false;
-  // Construct a SchemeHostPort with a dummy scheme and port to check that the
-  // hostname is valid.
-  url::SchemeHostPort scheme_host_port(
-      GURL(base::StringPrintf("http://%s:80", wildcards_replaced.c_str())));
-  if (scheme_host_port.IsInvalid())
-    return false;
-
-  // Check that wildcards only appear beyond the eTLD+1.
-  size_t registry_length =
-      net::registry_controlled_domains::PermissiveGetHostRegistryLength(
-          hostname_pattern,
-          net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
-          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-  // std::string::npos should only be returned for empty inputs, which should be
-  // filtered out by the IsInvalid() check above.
-  CHECK(registry_length != std::string::npos);
-  // If there is no registrar portion, the pattern is considered invalid.
-  if (registry_length == 0)
-    return false;
-  // If there is no component before the registrar portion, or if the component
-  // immediately preceding the registrar portion contains a wildcard, the
-  // pattern is not considered valid.
-  std::string host_before_registrar =
-      hostname_pattern.substr(0, hostname_pattern.size() - registry_length);
-  std::vector<std::string> components =
-      base::SplitString(host_before_registrar, ".", base::KEEP_WHITESPACE,
-                        base::SPLIT_WANT_NONEMPTY);
-  if (components.size() == 0)
-    return false;
-  if (components.back().find("*") != std::string::npos)
-    return false;
-  return true;
-}
-
-// Canonicalizes each component of |hostname_pattern|, making no changes to
-// wildcard components or components that fail canonicalization. For example,
-// given a |hostname_pattern| of "TeSt.*.%46oo.com", the output will be
-// "test.*.foo.com".
-std::string CanonicalizePatternComponents(const std::string& hostname_pattern) {
-  std::string canonical_host;  // Do not modify outside of canon_output.
-  canonical_host.reserve(hostname_pattern.length());
-  url::StdStringCanonOutput canon_output(&canonical_host);
-
-  for (size_t current = 0; current < hostname_pattern.length(); current++) {
-    size_t begin = current;
-
-    // Advance to next "." or end.
-    current = hostname_pattern.find('.', begin);
-    if (current == std::string::npos)
-      current = hostname_pattern.length();
-
-    // Try to append the canonicalized version of this component.
-    int current_len = base::checked_cast<int>(current - begin);
-    if (hostname_pattern.substr(begin, current_len) == "*" ||
-        !url::CanonicalizeHostSubstring(
-            hostname_pattern.data(),
-            url::Component(base::checked_cast<int>(begin), current_len),
-            &canon_output)) {
-      // Failed to canonicalize this component; append as-is.
-      canon_output.Append(hostname_pattern.substr(begin, current_len).data(),
-                          current_len);
-    }
-
-    if (current < hostname_pattern.length())
-      canon_output.push_back('.');
-  }
-  canon_output.Complete();
-  return canonical_host;
-}
-
-}  // namespace
 
 namespace secure_origin_whitelist {
 
-std::vector<std::string> ParseWhitelist(const std::string& origins_str) {
-  std::vector<std::string> origin_patterns;
-  for (const std::string& origin_str : base::SplitString(
-           origins_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
-    if (origin_str.find("*") != std::string::npos) {
-      if (IsValidWildcardPattern(origin_str)) {
-        std::string canonicalized_pattern =
-            CanonicalizePatternComponents(origin_str);
-        if (!canonicalized_pattern.empty()) {
-          origin_patterns.push_back(canonicalized_pattern);
-          continue;
-        }
-      }
-      LOG(ERROR) << "Whitelisted secure origin pattern " << origin_str
-                 << " is not valid; ignoring.";
-      continue;
-    }
-
-    // Drop .unique() origins, as they are unequal to any other origins.
-    url::Origin origin(url::Origin::Create(GURL(origin_str)));
-    if (!origin.opaque())
-      origin_patterns.push_back(origin.Serialize());
-  }
-
-  UMA_HISTOGRAM_COUNTS_100("Security.TreatInsecureOriginAsSecure",
-                           origin_patterns.size());
-
-#if defined(OS_CHROMEOS)
-  // For Crostini, we allow access to the default VM/container as a secure
-  // origin via the hostname penguin.linux.test. We are required to use a
-  // wildcard for the prefix because we do not know what the port number is.
-  // https://chromium.googlesource.com/chromiumos/docs/+/master/containers_and_vms.md
-  origin_patterns.push_back("*.linux.test");
-#endif
-
-  return origin_patterns;
-}
-
-std::vector<std::string> GetWhitelist() {
-  // If kUnsafelyTreatInsecureOriginAsSecure option is given, then treat the
-  // value as a comma-separated list of origins or origin patterns. Callers that
-  // need to also check the kUnsafelyTreatInsecureOriginAsSecure pref value must
-  // instead use ParseWhitelist directly (as there is no way for GetWhitelist()
-  // to access prefs). For renderer processes the pref and the switch will
-  // match, but for non-renderer processes the switch may not be set.
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  std::string origins_str = "";
-  if (command_line.HasSwitch(switches::kUnsafelyTreatInsecureOriginAsSecure)) {
-    origins_str = command_line.GetSwitchValueASCII(
-        switches::kUnsafelyTreatInsecureOriginAsSecure);
-  }
-  return ParseWhitelist(origins_str);
-}
-
 std::set<std::string> GetSchemesBypassingSecureContextCheck() {
   std::set<std::string> schemes;
   schemes.insert(extensions::kExtensionScheme);
diff --git a/chrome/common/secure_origin_whitelist.h b/chrome/common/secure_origin_whitelist.h
index 92b1fd9..65d7628 100644
--- a/chrome/common/secure_origin_whitelist.h
+++ b/chrome/common/secure_origin_whitelist.h
@@ -7,35 +7,11 @@
 
 #include <set>
 #include <string>
-#include <vector>
 
 class PrefRegistrySimple;
 
 namespace secure_origin_whitelist {
 
-// Return a whitelist of origins and hostname patterns that need to be
-// considered trustworthy.  The whitelist is given by
-// kUnsafelyTreatInsecureOriginAsSecure command-line option. See
-// https://www.w3.org/TR/powerful-features/#is-origin-trustworthy.
-//
-// The whitelist can contain origins and wildcard hostname patterns up to
-// eTLD+1. For example, the list may contain "http://foo.com",
-// "http://foo.com:8000", "*.foo.com", "*.foo.*.bar.com", and
-// "http://*.foo.bar.com", but not "*.co.uk", "*.com", or "test.*.com". Hostname
-// patterns must contain a wildcard somewhere (so "test.com" is not a valid
-// pattern) and wildcards can only replace full components ("test*.foo.com" is
-// not valid).
-//
-// Plain origins ("http://foo.com") are canonicalized when they are inserted
-// into this list by converting to url::Origin and serializing. For hostname
-// patterns, each component is individually canonicalized.
-std::vector<std::string> GetWhitelist();
-
-// Parses a comma-separated list of origins and wildcard hostname patterns.
-// This separate function allows callers other than GetWhitelist() to
-// explicitly pass a whitelist to be parsed.
-std::vector<std::string> ParseWhitelist(const std::string& origins_str);
-
 // Returns a whitelist of schemes that should bypass the Is Privileged Context
 // check. See http://www.w3.org/TR/powerful-features/#settings-privileged.
 std::set<std::string> GetSchemesBypassingSecureContextCheck();
diff --git a/chrome/common/secure_origin_whitelist_unittest.cc b/chrome/common/secure_origin_whitelist_unittest.cc
deleted file mode 100644
index e71c9e1..0000000
--- a/chrome/common/secure_origin_whitelist_unittest.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/test/scoped_command_line.h"
-#include "chrome/common/chrome_switches.h"
-#include "content/public/common/origin_util.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using content::IsOriginSecure;
-
-namespace chrome {
-
-class SecureOriginWhiteListTest : public testing::Test {
-  void TearDown() override {
-    // Ensure that we reset the whitelisted origins without any flags applied.
-    content::ResetSchemesAndOriginsWhitelist();
-  }
-};
-
-TEST_F(SecureOriginWhiteListTest, UnsafelyTreatInsecureOriginAsSecure) {
-  EXPECT_FALSE(content::IsOriginSecure(GURL("http://example.com/a.html")));
-  EXPECT_FALSE(
-      content::IsOriginSecure(GURL("http://127.example.com/a.html")));
-  // Add http://example.com and http://127.example.com to whitelist by
-  // command-line and see if they are now considered secure origins.
-  // (The command line is applied via
-  // ChromeContentClient::AddSecureSchemesAndOrigins)
-  base::test::ScopedCommandLine scoped_command_line;
-  base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
-  command_line->AppendSwitchASCII(
-      switches::kUnsafelyTreatInsecureOriginAsSecure,
-      "http://example.com,http://127.example.com");
-  content::ResetSchemesAndOriginsWhitelist();
-
-  // They should be now white-listed.
-  EXPECT_TRUE(content::IsOriginSecure(GURL("http://example.com/a.html")));
-  EXPECT_TRUE(content::IsOriginSecure(GURL("http://127.example.com/a.html")));
-
-  // Check that similarly named sites are not considered secure.
-  EXPECT_FALSE(content::IsOriginSecure(GURL("http://128.example.com/a.html")));
-  EXPECT_FALSE(content::IsOriginSecure(
-      GURL("http://foobar.127.example.com/a.html")));
-}
-
-TEST_F(SecureOriginWhiteListTest, HostnamePatterns) {
-  const struct HostnamePatternCase {
-    const char* pattern;
-    const char* test_input;
-    bool expected_secure;
-  } kTestCases[] = {
-      {"*.foo.com", "http://bar.foo.com", true},
-      {"*.foo.*.bar.com", "http://a.foo.b.bar.com:8000", true},
-      // For parsing/canonicalization simplicity, wildcard patterns can be
-      // hostnames only, not full origins.
-      {"http://*.foo.com", "http://bar.foo.com", false},
-      {"*://foo.com", "http://foo.com", false},
-      // Wildcards must be beyond eTLD+1.
-      {"*.co.uk", "http://foo.co.uk", false},
-      {"*.co.uk", "http://co.uk", false},
-      {"*.baz", "http://foo.baz", false},
-      {"foo.*.com", "http://foo.bar.com", false},
-      {"*.foo.baz", "http://a.foo.baz", true},
-      // Hostname patterns should be canonicalized.
-      {"*.FoO.com", "http://a.foo.com", true},
-      {"%2A.foo.com", "http://a.foo.com", false},
-      // Hostname patterns must contain a wildcard and a wildcard can only
-      // replace a component, not a part of a component.
-      {"foo.com", "http://foo.com", false},
-      {"test*.foo.com", "http://testblah.foo.com", false},
-      {"*foo.com", "http://testfoo.com", false},
-      {"foo*.com", "http://footest.com", false},
-  };
-
-  for (const auto& test : kTestCases) {
-    base::test::ScopedCommandLine scoped_command_line;
-    base::CommandLine* command_line =
-        scoped_command_line.GetProcessCommandLine();
-    command_line->AppendSwitchASCII(
-        switches::kUnsafelyTreatInsecureOriginAsSecure, test.pattern);
-    content::ResetSchemesAndOriginsWhitelist();
-    EXPECT_EQ(test.expected_secure,
-              content::IsOriginSecure(GURL(test.test_input)));
-    EXPECT_EQ(test.expected_secure,
-              content::IsPotentiallyTrustworthyOrigin(
-                  url::Origin::Create(GURL(test.test_input))));
-  }
-}
-
-}  // namespace chrome
diff --git a/chrome/credential_provider/gaiacp/associated_user_validator.cc b/chrome/credential_provider/gaiacp/associated_user_validator.cc
index 44a9a9bd..c52eccf9 100644
--- a/chrome/credential_provider/gaiacp/associated_user_validator.cc
+++ b/chrome/credential_provider/gaiacp/associated_user_validator.cc
@@ -279,7 +279,7 @@
 
   HRESULT hr = UpdateAssociatedSids(nullptr);
   if (FAILED(hr)) {
-    LOGFN(ERROR) << "GetUserTokenHandles hr=" << putHR(hr);
+    LOGFN(ERROR) << "UpdateAssociatedSids hr=" << putHR(hr);
     return;
   }
 
@@ -311,6 +311,26 @@
   return S_OK;
 }
 
+void AssociatedUserValidator::AllowSigninForAllAssociatedUsers(
+    CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus) {
+  if (!MdmEnrollmentEnabled() ||
+      !CGaiaCredentialProvider::IsUsageScenarioSupported(cpus))
+    return;
+
+  std::map<base::string16, base::string16> sids_to_handle;
+  HRESULT hr = UpdateAssociatedSids(&sids_to_handle);
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "UpdateAssociatedSids hr=" << putHR(hr);
+    return;
+  }
+
+  auto policy = ScopedLsaPolicy::Create(POLICY_ALL_ACCESS);
+  for (const auto& sid_to_handle : sids_to_handle)
+    ModifyUserAccess(policy, sid_to_handle.first, true);
+
+  locked_user_sids_.clear();
+}
+
 void AssociatedUserValidator::AllowSigninForUsersWithInvalidTokenHandles() {
   LOGFN(INFO);
   auto policy = ScopedLsaPolicy::Create(POLICY_ALL_ACCESS);
diff --git a/chrome/credential_provider/gaiacp/associated_user_validator.h b/chrome/credential_provider/gaiacp/associated_user_validator.h
index 7818c1f..f2694874 100644
--- a/chrome/credential_provider/gaiacp/associated_user_validator.h
+++ b/chrome/credential_provider/gaiacp/associated_user_validator.h
@@ -66,6 +66,12 @@
   // token validator.
   void AllowSigninForUsersWithInvalidTokenHandles();
 
+  // Restores access to all associated users. Regardless of their access
+  // state. This ensures that no user can be completely locked out due
+  // a bad computer state or crash.
+  void AllowSigninForAllAssociatedUsers(
+      CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus);
+
   // Fills |associated_sids| with the sids of all valid associated users
   // found on this system.
   std::set<base::string16> GetUpdatedAssociatedSids();
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc
index 8cd1bb6..0516b58 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc
@@ -28,6 +28,9 @@
     GUID* providers_clsids,
     BOOL* providers_allow,
     DWORD providers_count) {
+  // Re-enable all users in case internet has been lost or the computer
+  // crashed while users were locked out.
+  AssociatedUserValidator::Get()->AllowSigninForAllAssociatedUsers(cpus);
   // Check to see if any users need to have their access to this system
   // using the normal credential providers revoked.
   AssociatedUserValidator::Get()->DenySigninForUsersWithInvalidTokenHandles(
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 82ac3067..a838fabb 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -22,7 +22,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "build/build_config.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_content_client.h"
@@ -114,6 +113,7 @@
 #include "ppapi/buildflags/buildflags.h"
 #include "ppapi/shared_impl/ppapi_switches.h"
 #include "printing/buildflags/buildflags.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
@@ -148,6 +148,9 @@
 #include "chrome/renderer/searchbox/searchbox_extension.h"
 #endif
 
+#if defined(OS_WIN)
+#endif
+
 #if defined(FULL_SAFE_BROWSING)
 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
 #endif
@@ -293,52 +296,13 @@
   DISALLOW_COPY_AND_ASSIGN(MediaLoadDeferrer);
 };
 
-#if defined(OS_WIN)
-// Binds |module_event_sink| to the provided |interface_ptr_info|. This function
-// is used to do the binding on the IO thread.
-void BindModuleEventSink(mojom::ModuleEventSinkPtr* module_event_sink,
-                         mojom::ModuleEventSinkPtrInfo interface_ptr_info) {
-  DCHECK(!module_event_sink->is_bound());
-
-  module_event_sink->Bind(std::move(interface_ptr_info));
-}
-
-// Dispatches a module |event| to the provided |module_event_sink| interface.
-// It is expected that this only be called from the IO thread. This is only safe
-// because the underlying |module_event_sink| object is never deleted, being
-// owned by the leaked ChromeContentRendererClient object. If this ever changes
-// then a WeakPtr mechanism would have to be used.
-void HandleModuleEventOnIOThread(
-    const mojom::ModuleEventSinkPtr& module_event_sink,
-    const ModuleWatcher::ModuleEvent& event) {
-  DCHECK(module_event_sink.is_bound());
-
-  // Simply send the module load address. The browser can validate this and look
-  // up the module details on its own.
-  module_event_sink->OnModuleEvent(
-      event.event_type, reinterpret_cast<uintptr_t>(event.module_load_address));
-}
-
-// Receives notifications from the ModuleWatcher on any thread. Bounces these
-// over to the provided |io_task_runner| where they are subsequently dispatched
-// to the |module_event_sink| interface.
-void OnModuleEvent(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-                   const mojom::ModuleEventSinkPtr& module_event_sink,
-                   const ModuleWatcher::ModuleEvent& event) {
-  // The Mojo interface can only be used from a single thread. Bounce tasks
-  // over to it. It is safe to pass an unretained pointer to
-  // |module_event_sink|: it is owned by a ChromeContentRendererClient, which is
-  // a leaked singleton in the process.
-  io_task_runner->PostTask(FROM_HERE,
-                           base::BindOnce(&HandleModuleEventOnIOThread,
-                                          std::cref(module_event_sink), event));
-}
-#endif
-
 }  // namespace
 
 ChromeContentRendererClient::ChromeContentRendererClient()
     : main_entry_time_(base::TimeTicks::Now()),
+#if defined(OS_WIN)
+      remote_module_watcher_(nullptr, base::OnTaskRunnerDeleter(nullptr)),
+#endif
       main_thread_profiler_(ThreadProfiler::CreateAndStartOnMainThread()) {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   EnsureExtensionsClientInitialized();
@@ -370,26 +334,8 @@
   }
 
 #if defined(OS_WIN)
-  // Bind the ModuleEventSink interface.
-  thread->GetConnector()->BindInterface(
-      service_manager::ServiceFilter::ByName(
-          content::mojom::kBrowserServiceName),
-      &module_event_sink_);
-
-  // Rebind the ModuleEventSink to the IO task runner.
-  // The use of base::Unretained() is safe here because |module_event_sink_|
-  // is never deleted and is only used on the IO task runner.
-  thread->GetIOTaskRunner()->PostTask(
-      FROM_HERE, base::BindOnce(&BindModuleEventSink,
-                                base::Unretained(&module_event_sink_),
-                                module_event_sink_.PassInterface()));
-
-  // It is safe to pass an unretained pointer to |module_event_sink_|, as it
-  // is owned by the process singleton ChromeContentRendererClient, which is
-  // leaked.
-  module_watcher_ = ModuleWatcher::Create(
-      base::BindRepeating(&OnModuleEvent, thread->GetIOTaskRunner(),
-                          std::cref(module_event_sink_)));
+  remote_module_watcher_ = RemoteModuleWatcher::Create(
+      thread->GetIOTaskRunner(), thread->GetConnector());
 #endif
 
   chrome_observer_.reset(new ChromeRenderThreadObserver());
@@ -463,8 +409,7 @@
   pdf::PepperPDFHost::SetPrintClient(pdf_print_client_.get());
 #endif
 
-  for (auto& origin_or_hostname_pattern :
-       secure_origin_whitelist::GetWhitelist()) {
+  for (auto& origin_or_hostname_pattern : network::GetSecureOriginAllowlist()) {
     WebSecurityPolicy::AddOriginTrustworthyWhiteList(
         WebString::FromUTF8(origin_or_hostname_pattern));
   }
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index c9c7992..d64bb63 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -16,6 +16,7 @@
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
+#include "build/build_config.h"
 #include "chrome/common/plugin.mojom.h"
 #include "chrome/renderer/media/chrome_key_systems_provider.h"
 #include "components/nacl/common/buildflags.h"
@@ -36,8 +37,7 @@
 #include "v8/include/v8.h"
 
 #if defined(OS_WIN)
-#include "chrome/common/conflicts/module_event_sink_win.mojom.h"
-#include "chrome/common/conflicts/module_watcher_win.h"
+#include "chrome/common/conflicts/remote_module_watcher_win.h"
 #endif
 
 class ChromeRenderThreadObserver;
@@ -269,6 +269,13 @@
 
   service_manager::Connector* GetConnector();
 
+#if defined(OS_WIN)
+  // Observes module load events and notifies the ModuleDatabase in the browser
+  // process. This instance is created on the main thread but then lives on the
+  // IO task runner.
+  RemoteModuleWatcher::UniquePtr remote_module_watcher_;
+#endif
+
   // Used to profile main thread.
   std::unique_ptr<ThreadProfiler> main_thread_profiler_;
 
@@ -296,13 +303,6 @@
   std::set<std::string> allowed_camera_device_origins_;
 #endif
 
-#if defined(OS_WIN)
-  // Observes module load and unload events and notifies the ModuleDatabase in
-  // the browser process.
-  std::unique_ptr<ModuleWatcher> module_watcher_;
-  mojom::ModuleEventSinkPtr module_event_sink_;
-#endif
-
   service_manager::ServiceBinding service_binding_{this};
   service_manager::BinderRegistry registry_;
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index cacf16a..eef65e5 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2701,7 +2701,6 @@
     "../browser/net/file_downloader_unittest.cc",
     "../browser/net/net_error_tab_helper_unittest.cc",
     "../browser/net/probe_message_unittest.cc",
-    "../browser/net/quota_policy_channel_id_store_unittest.cc",
     "../browser/net/reporting_permissions_checker_unittest.cc",
     "../browser/notifications/metrics/notification_metrics_logger_unittest.cc",
     "../browser/notifications/notification_channels_provider_android_unittest.cc",
@@ -2954,6 +2953,7 @@
     "../common/chrome_paths_unittest.cc",
     "../common/component_flash_hint_file_linux_unittest.cc",
     "../common/conflicts/module_watcher_win_unittest.cc",
+    "../common/conflicts/remote_module_watcher_win_unittest.cc",
     "../common/crash_keys_unittest.cc",
     "../common/heap_profiler_controller_unittest.cc",
     "../common/ini_parser_unittest.cc",
@@ -2970,7 +2970,6 @@
     "../common/page_load_metrics/test/weak_mock_timer.cc",
     "../common/page_load_metrics/test/weak_mock_timer.h",
     "../common/pref_names_util_unittest.cc",
-    "../common/secure_origin_whitelist_unittest.cc",
     "../common/thread_profiler_unittest.cc",
     "../renderer/chrome_content_renderer_client_unittest.cc",
     "../renderer/content_settings_observer_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 1a82e9e..932b33d 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -89,11 +89,11 @@
     "//net/android:net_java_test_support",
     "//testing/android/reporter:reporter_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_compat_java",
-    "//third_party/android_deps:android_support_design_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_design_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/hamcrest:hamcrest_core_java",
diff --git a/chrome/test/android/cast_emulator/BUILD.gn b/chrome/test/android/cast_emulator/BUILD.gn
index 78c1d04..251a13cb 100644
--- a/chrome/test/android/cast_emulator/BUILD.gn
+++ b/chrome/test/android/cast_emulator/BUILD.gn
@@ -23,6 +23,6 @@
     "$google_play_services_package:google_play_services_cast_java",
     "//base:base_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_mediarouter_java",
+    "//third_party/android_deps:com_android_support_mediarouter_v7_java",
   ]
 }
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js b/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js
index 5a6a890..4e523cc 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js
@@ -149,3 +149,29 @@
 TEST_F('CrElementsIconButtonFocusTest', 'All', function() {
   mocha.run();
 });
+
+
+/**
+ * @constructor
+ * @extends {CrElementsFocusTest}
+ */
+function CrElementsExpandButtonTest() {}
+
+CrElementsExpandButtonTest.prototype = {
+  __proto__: CrElementsFocusTest.prototype,
+
+  /** @override */
+  browsePreload:
+      'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html',
+
+  /** @override */
+  extraLibraries: CrElementsFocusTest.prototype.extraLibraries.concat([
+    ROOT_PATH + 'ui/webui/resources/js/util.js',
+    '../settings/test_util.js',
+    'cr_expand_button_focus_tests.js',
+  ]),
+};
+
+TEST_F('CrElementsExpandButtonTest', 'All', function() {
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/cr_elements/cr_expand_button_focus_tests.js b/chrome/test/data/webui/cr_elements/cr_expand_button_focus_tests.js
new file mode 100644
index 0000000..a6833230
--- /dev/null
+++ b/chrome/test/data/webui/cr_elements/cr_expand_button_focus_tests.js
@@ -0,0 +1,120 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+suite('cr-expand-button-focus-tests', () => {
+  let button;
+
+  /** @param {boolean} */
+  function assertRippleState(rippleShown) {
+    assertEquals(button.$.icon, getDeepActiveElement());
+    assertEquals(rippleShown, button.$.icon.getRipple().holdDown);
+  }
+
+  function assertRipple() {
+    assertRippleState(true);
+  }
+
+  function assertNoRipple() {
+    assertRippleState(false);
+  }
+
+  /** @param {!Function} toggler */
+  async function waitForExpansion(toggler) {
+    const wait = test_util.eventToPromise('expanded-changed', button);
+    toggler();
+    await wait;
+  }
+
+  async function click() {
+    await waitForExpansion(() => {
+      // This is used in cr.ui.focusWithoutInk to change mode into ink hidden
+      // when focused.
+      button.dispatchEvent(new PointerEvent('pointerdown'));
+      // Used to simulate releasing the mouse button.
+      button.$.icon.fire('up');
+      // When the mouse is pressed and released, it will also emit a 'click'
+      // event which is used in cr-expand-button to toggle expansion.
+      button.fire('click');
+    });
+  }
+
+  async function enter() {
+    await waitForExpansion(() => {
+      MockInteractions.pressAndReleaseKeyOn(button.$.icon, '', '', 'Enter');
+    });
+  }
+
+  async function space() {
+    await waitForExpansion(() => {
+      MockInteractions.pressAndReleaseKeyOn(button.$.icon, '', '', ' ');
+    });
+  }
+
+  setup(() => {
+    document.body.innerHTML = '<cr-expand-button></cr-expand-button>';
+    button = document.body.querySelector('cr-expand-button');
+  });
+
+  test('focus, ripple', () => {
+    button.focus();
+    assertRipple();
+  });
+
+  test('click, no ripple', async () => {
+    await click();
+    assertNoRipple();
+  });
+
+  test('enter, ripple', async () => {
+    await enter();
+    assertRipple();
+  });
+
+  test('space, ripple', async () => {
+    await space();
+    assertRipple();
+  });
+
+  test('focus then click, no ripple', async () => {
+    button.focus();
+    await click();
+    assertNoRipple();
+  });
+
+  test('click then enter, no ripple', async () => {
+    await click();
+    await enter();
+    assertNoRipple();
+  });
+
+  test('click then space, no ripple', async () => {
+    await click();
+    await space();
+    assertNoRipple();
+  });
+
+  test('enter then click, no ripple', async () => {
+    await enter();
+    await click();
+    assertNoRipple();
+  });
+
+  test('space then click, no ripple', async () => {
+    await space();
+    await click();
+    assertNoRipple();
+  });
+
+  test('focus then enter, ripple', async () => {
+    button.focus();
+    await enter();
+    assertRipple();
+  });
+
+  test('focus then space, ripple', async () => {
+    button.focus();
+    await space();
+    assertRipple();
+  });
+});
diff --git a/chrome/test/data/webui/cr_elements/cr_policy_strings.js b/chrome/test/data/webui/cr_elements/cr_policy_strings.js
index a3b62793..5c1c966 100644
--- a/chrome/test/data/webui/cr_elements/cr_policy_strings.js
+++ b/chrome/test/data/webui/cr_elements/cr_policy_strings.js
@@ -9,7 +9,8 @@
   controlledSettingRecommendedMatches: 'matches',
   controlledSettingRecommendedDiffers: 'differs',
   controlledSettingShared: 'shared: $1',
-  controlledSettingOwner: 'owner: $1',
+  controlledSettingWithOwner: 'owner: $1',
+  controlledSettingNoOwner: 'owner',
   controlledSettingExtension: 'extension: $1',
   controlledSettingExtensionWithoutName: 'extension',
 };
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index f777f46..75ce77a 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -106,12 +106,6 @@
     "media/media_caps_impl.h",
     "media/supported_codec_finder.cc",
     "media/supported_codec_finder.h",
-    "metrics/cast_metrics_prefs.cc",
-    "metrics/cast_metrics_prefs.h",
-    "metrics/cast_metrics_service_client.cc",
-    "metrics/cast_metrics_service_client.h",
-    "metrics/cast_stability_metrics_provider.cc",
-    "metrics/cast_stability_metrics_provider.h",
     "renderer_prelauncher.cc",
     "renderer_prelauncher.h",
     "service/cast_service_simple.cc",
@@ -138,6 +132,7 @@
   public_deps = [
     ":prefs",
     ":public",
+    "//chromecast/browser/metrics",
   ]
 
   deps = [
@@ -226,14 +221,9 @@
       "cast_memory_pressure_monitor.h",
       "memory_pressure_controller_impl.cc",
       "memory_pressure_controller_impl.h",
-      "metrics/external_metrics.cc",
-      "metrics/external_metrics.h",
     ]
 
-    deps += [
-      "//components/metrics:serialization",
-      "//third_party/fontconfig",
-    ]
+    deps += [ "//third_party/fontconfig" ]
   }
 
   if (use_aura) {
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn
index 93952de..05bb46f 100644
--- a/chromecast/browser/android/BUILD.gn
+++ b/chromecast/browser/android/BUILD.gn
@@ -93,7 +93,7 @@
   deps = [
     "//base:base_java",
     "//chromecast/base:base_java",
-    "//third_party/android_deps:android_support_core_utils_java",
+    "//third_party/android_deps:com_android_support_support_core_utils_java",
   ]
 }
 
@@ -149,7 +149,7 @@
     "//net/android:net_java",
 
     # TODO(slan): We may need to pass this in as a parameter.
-    "//third_party/android_deps:android_support_core_utils_java",
+    "//third_party/android_deps:com_android_support_support_core_utils_java",
     "//ui/android:ui_java",
   ]
 
@@ -210,7 +210,7 @@
     "//base:base_junit_test_support",
     "//chromecast/base:cast_base_test_utils_java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:android_support_core_utils_java",
+    "//third_party/android_deps:com_android_support_support_core_utils_java",
     "//third_party/hamcrest:hamcrest_java",
   ]
 }
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 17205215..4b6e811f 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -477,6 +477,7 @@
       std::make_unique<CastBrowserContext>(url_request_context_factory_));
   cast_browser_process_->SetMetricsServiceClient(
       std::make_unique<metrics::CastMetricsServiceClient>(
+          cast_browser_process_->browser_client(),
           cast_browser_process_->pref_service(),
           content::BrowserContext::GetDefaultStoragePartition(
               cast_browser_process_->browser_context())
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 1e1f5c26f..41da499 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -15,6 +15,7 @@
 #include "base/threading/thread.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "chromecast/browser/metrics/cast_metrics_service_client.h"
 #include "chromecast/chromecast_buildflags.h"
 #include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/content_browser_client.h"
@@ -67,7 +68,9 @@
 class CastResourceDispatcherHostDelegate;
 class URLRequestContextFactory;
 
-class CastContentBrowserClient : public content::ContentBrowserClient {
+class CastContentBrowserClient
+    : public content::ContentBrowserClient,
+      public chromecast::metrics::CastMetricsServiceDelegate {
  public:
   // Creates an implementation of CastContentBrowserClient. Platform should
   // link in an implementation as needed.
@@ -118,12 +121,10 @@
   virtual base::WeakPtr<device::BluetoothAdapterCast> CreateBluetoothAdapter();
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
-  // Invoked when the metrics client ID changes.
-  virtual void SetMetricsClientId(const std::string& client_id);
-
-  // Allows registration of extra metrics providers.
-  virtual void RegisterMetricsProviders(
-      ::metrics::MetricsService* metrics_service);
+  // chromecast::metrics::CastMetricsServiceDelegate implementation:
+  void SetMetricsClientId(const std::string& client_id) override;
+  void RegisterMetricsProviders(
+      ::metrics::MetricsService* metrics_service) override;
 
   // Returns whether or not the remote debugging service should be started
   // on browser startup.
diff --git a/chromecast/browser/cast_network_contexts.cc b/chromecast/browser/cast_network_contexts.cc
index 169f0c2..58653a5 100644
--- a/chromecast/browser/cast_network_contexts.cc
+++ b/chromecast/browser/cast_network_contexts.cc
@@ -126,6 +126,9 @@
 CastNetworkContexts::~CastNetworkContexts() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  if (proxy_config_service_)
+    proxy_config_service_->RemoveObserver(this);
+
   system_shared_url_loader_factory_->Shutdown();
 }
 
diff --git a/chromecast/browser/metrics/BUILD.gn b/chromecast/browser/metrics/BUILD.gn
index 9e037513..1055295 100644
--- a/chromecast/browser/metrics/BUILD.gn
+++ b/chromecast/browser/metrics/BUILD.gn
@@ -18,13 +18,17 @@
     "//base",
     "//base:i18n",
     "//chromecast/base",
-    "//chromecast/common",
+    "//chromecast/base:cast_sys_info",
+    "//chromecast/base:cast_version",
     "//components/metrics",
     "//components/metrics:gpu",
     "//components/metrics:net",
+    "//components/metrics:ui",
     "//components/prefs",
     "//content/public/browser",
     "//content/public/common",
+    "//services/network/public/cpp",
+    "//third_party/metrics_proto",
   ]
 
   if (is_linux) {
@@ -33,6 +37,9 @@
       "external_metrics.h",
     ]
 
-    deps += [ "//components/metrics:serialization" ]
+    deps += [
+      "//chromecast/base/metrics",
+      "//components/metrics:serialization",
+    ]
   }
 }
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.cc b/chromecast/browser/metrics/cast_metrics_service_client.cc
index ab7cb3b..645835f 100644
--- a/chromecast/browser/metrics/cast_metrics_service_client.cc
+++ b/chromecast/browser/metrics/cast_metrics_service_client.cc
@@ -18,8 +18,6 @@
 #include "chromecast/base/path_utils.h"
 #include "chromecast/base/pref_names.h"
 #include "chromecast/base/version.h"
-#include "chromecast/browser/cast_browser_process.h"
-#include "chromecast/browser/cast_content_browser_client.h"
 #include "chromecast/browser/metrics/cast_stability_metrics_provider.h"
 #include "chromecast/public/cast_sys_info.h"
 #include "components/metrics/client_info.h"
@@ -108,8 +106,8 @@
     const std::string& client_id) {
   client_id_ = client_id;
   LOG(INFO) << "Metrics client ID set: " << client_id;
-  shell::CastBrowserProcess::GetInstance()->browser_client()->
-      SetMetricsClientId(client_id);
+  if (delegate_)
+    delegate_->SetMetricsClientId(client_id);
 #if defined(OS_ANDROID)
   DumpstateWriter::AddDumpValue(kClientIdName, client_id);
 #endif
@@ -276,9 +274,11 @@
 }
 
 CastMetricsServiceClient::CastMetricsServiceClient(
+    CastMetricsServiceDelegate* delegate,
     PrefService* pref_service,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
-    : pref_service_(pref_service),
+    : delegate_(delegate),
+      pref_service_(pref_service),
       client_info_loaded_(false),
 #if defined(OS_LINUX)
       external_metrics_(nullptr),
@@ -340,7 +340,7 @@
   SetMetricsClientId(metrics_state_manager_->client_id());
 
   CastStabilityMetricsProvider* stability_provider =
-      new CastStabilityMetricsProvider(metrics_service_.get());
+      new CastStabilityMetricsProvider(metrics_service_.get(), pref_service_);
   metrics_service_->RegisterMetricsProvider(
       std::unique_ptr<::metrics::MetricsProvider>(stability_provider));
 
@@ -359,8 +359,8 @@
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<::metrics::NetworkMetricsProvider>(
           content::CreateNetworkConnectionTrackerAsyncGetter()));
-  shell::CastBrowserProcess::GetInstance()->browser_client()->
-      RegisterMetricsProviders(metrics_service_.get());
+  if (delegate_)
+    delegate_->RegisterMetricsProviders(metrics_service_.get());
 
   metrics_service_->InitializeMetricsRecordingState();
 #if !defined(OS_ANDROID)
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.h b/chromecast/browser/metrics/cast_metrics_service_client.h
index 1fe3c5ba..0f056d3a 100644
--- a/chromecast/browser/metrics/cast_metrics_service_client.h
+++ b/chromecast/browser/metrics/cast_metrics_service_client.h
@@ -37,12 +37,24 @@
 namespace chromecast {
 namespace metrics {
 
+class CastMetricsServiceDelegate {
+ public:
+  // Invoked when the metrics client ID changes.
+  virtual void SetMetricsClientId(const std::string& client_id) = 0;
+  // Allows registration of extra metrics providers.
+  virtual void RegisterMetricsProviders(::metrics::MetricsService* service) = 0;
+
+ protected:
+  virtual ~CastMetricsServiceDelegate() = default;
+};
+
 class ExternalMetrics;
 
 class CastMetricsServiceClient : public ::metrics::MetricsServiceClient,
                                  public ::metrics::EnabledStateProvider {
  public:
   CastMetricsServiceClient(
+      CastMetricsServiceDelegate* delegate,
       PrefService* pref_service,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
   ~CastMetricsServiceClient() override;
@@ -93,6 +105,7 @@
   std::unique_ptr<::metrics::ClientInfo> LoadClientInfo();
   void StoreClientInfo(const ::metrics::ClientInfo& client_info);
 
+  CastMetricsServiceDelegate* const delegate_;
   PrefService* const pref_service_;
   std::string client_id_;
   std::string force_client_id_;
diff --git a/chromecast/browser/metrics/cast_stability_metrics_provider.cc b/chromecast/browser/metrics/cast_stability_metrics_provider.cc
index cd252b03..e22c89f 100644
--- a/chromecast/browser/metrics/cast_stability_metrics_provider.cc
+++ b/chromecast/browser/metrics/cast_stability_metrics_provider.cc
@@ -10,7 +10,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "chromecast/base/pref_names.h"
-#include "chromecast/browser/cast_browser_process.h"
 #include "chromecast/browser/metrics/cast_metrics_service_client.h"
 #include "components/metrics/metrics_service.h"
 #include "components/prefs/pref_registry_simple.h"
@@ -37,13 +36,6 @@
   RENDERER_TYPE_COUNT
 };
 
-void IncrementPrefValue(const char* path) {
-  PrefService* pref = shell::CastBrowserProcess::GetInstance()->pref_service();
-  DCHECK(pref);
-  int value = pref->GetInteger(path);
-  pref->SetInteger(path, value + 1);
-}
-
 // Converts an exit code into something that can be inserted into our
 // histograms (which expect non-negative numbers less than MAX_INT).
 int MapCrashExitCodeForHistogram(int exit_code) {
@@ -61,8 +53,10 @@
 }
 
 CastStabilityMetricsProvider::CastStabilityMetricsProvider(
-    ::metrics::MetricsService* metrics_service)
-    : metrics_service_(metrics_service) {
+    ::metrics::MetricsService* metrics_service,
+    PrefService* pref_service)
+    : metrics_service_(metrics_service), pref_service_(pref_service) {
+  DCHECK(pref_service_);
   BrowserChildProcessObserver::Add(this);
 }
 
@@ -85,32 +79,32 @@
 
 void CastStabilityMetricsProvider::ProvideStabilityMetrics(
     ::metrics::SystemProfileProto* system_profile_proto) {
-  PrefService* pref = shell::CastBrowserProcess::GetInstance()->pref_service();
   ::metrics::SystemProfileProto_Stability* stability_proto =
       system_profile_proto->mutable_stability();
 
-  int count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
+  int count =
+      pref_service_->GetInteger(prefs::kStabilityChildProcessCrashCount);
   if (count) {
     stability_proto->set_child_process_crash_count(count);
-    pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
+    pref_service_->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
   }
 
-  count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
+  count = pref_service_->GetInteger(prefs::kStabilityRendererCrashCount);
   if (count) {
     stability_proto->set_renderer_crash_count(count);
-    pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
+    pref_service_->SetInteger(prefs::kStabilityRendererCrashCount, 0);
   }
 
-  count = pref->GetInteger(prefs::kStabilityRendererFailedLaunchCount);
+  count = pref_service_->GetInteger(prefs::kStabilityRendererFailedLaunchCount);
   if (count) {
     stability_proto->set_renderer_failed_launch_count(count);
-    pref->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0);
+    pref_service_->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0);
   }
 
-  count = pref->GetInteger(prefs::kStabilityRendererHangCount);
+  count = pref_service_->GetInteger(prefs::kStabilityRendererHangCount);
   if (count) {
     stability_proto->set_renderer_hang_count(count);
-    pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
+    pref_service_->SetInteger(prefs::kStabilityRendererHangCount, 0);
   }
 }
 
@@ -188,5 +182,10 @@
   IncrementPrefValue(prefs::kStabilityRendererHangCount);
 }
 
+void CastStabilityMetricsProvider::IncrementPrefValue(const char* path) {
+  int value = pref_service_->GetInteger(path);
+  pref_service_->SetInteger(path, value + 1);
+}
+
 }  // namespace metrics
 }  // namespace chromecast
diff --git a/chromecast/browser/metrics/cast_stability_metrics_provider.h b/chromecast/browser/metrics/cast_stability_metrics_provider.h
index c4b2dee..966d647 100644
--- a/chromecast/browser/metrics/cast_stability_metrics_provider.h
+++ b/chromecast/browser/metrics/cast_stability_metrics_provider.h
@@ -13,6 +13,7 @@
 #include "content/public/browser/notification_registrar.h"
 
 class PrefRegistrySimple;
+class PrefService;
 
 namespace content {
 class RenderProcessHost;
@@ -35,8 +36,8 @@
   // Registers local state prefs used by this class.
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
-  explicit CastStabilityMetricsProvider(
-      ::metrics::MetricsService* metrics_service);
+  CastStabilityMetricsProvider(::metrics::MetricsService* metrics_service,
+                               PrefService* pref_service);
   ~CastStabilityMetricsProvider() override;
 
   // metrics::MetricsDataProvider implementation:
@@ -67,6 +68,9 @@
   // Records a renderer process hang.
   void LogRendererHang();
 
+  // Increments the specified pref by 1.
+  void IncrementPrefValue(const char* path);
+
   // Registrar for receiving stability-related notifications.
   content::NotificationRegistrar registrar_;
 
@@ -75,6 +79,8 @@
   // CastStabilityMetricsProvider.
   ::metrics::MetricsService* metrics_service_;
 
+  PrefService* const pref_service_;
+
   DISALLOW_COPY_AND_ASSIGN(CastStabilityMetricsProvider);
 };
 
diff --git a/chromecast/media/cma/backend/android/BUILD.gn b/chromecast/media/cma/backend/android/BUILD.gn
index 96e8ead..b05a52da 100644
--- a/chromecast/media/cma/backend/android/BUILD.gn
+++ b/chromecast/media/cma/backend/android/BUILD.gn
@@ -73,8 +73,8 @@
     "//base:base_java",
     "//chromecast/base:base_java",
     "//chromecast/public:volume_control_enums_java",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_v13_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_v13_java",
   ]
 }
 
diff --git a/chromecast/public/BUILD.gn b/chromecast/public/BUILD.gn
index 99730d0..d14f84d3 100644
--- a/chromecast/public/BUILD.gn
+++ b/chromecast/public/BUILD.gn
@@ -50,7 +50,7 @@
   android_library("volume_control_enums_java") {
     srcjar_deps = [ ":java_enums_volume_control" ]
     deps = [
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index b6ada5b5..2c0bbb31 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-11919.0.0
\ No newline at end of file
+11921.0.0
\ No newline at end of file
diff --git a/chromeos/components/account_manager/BUILD.gn b/chromeos/components/account_manager/BUILD.gn
index 8118946..04bdc5e 100644
--- a/chromeos/components/account_manager/BUILD.gn
+++ b/chromeos/components/account_manager/BUILD.gn
@@ -20,6 +20,8 @@
 
   deps = [
     "//base",
+    "//chromeos/constants",
+    "//components/prefs:prefs",
     "//google_apis",
     "//net",
     "//services/network/public/cpp:cpp",
diff --git a/chromeos/components/account_manager/account_manager.cc b/chromeos/components/account_manager/account_manager.cc
index 65e01726..4c01feb6 100644
--- a/chromeos/components/account_manager/account_manager.cc
+++ b/chromeos/components/account_manager/account_manager.cc
@@ -17,6 +17,8 @@
 #include "base/task/post_task.h"
 #include "base/task_runner_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "chromeos/constants/chromeos_pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
@@ -127,6 +129,13 @@
 
 AccountManager::AccountManager() : weak_factory_(this) {}
 
+// static
+void AccountManager::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterBooleanPref(
+      chromeos::prefs::kSecondaryGoogleAccountSigninAllowed,
+      true /* default_value */);
+}
+
 void AccountManager::Initialize(
     const base::FilePath& home_dir,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
diff --git a/chromeos/components/account_manager/account_manager.h b/chromeos/components/account_manager/account_manager.h
index 1d29aaf..b0e106fd 100644
--- a/chromeos/components/account_manager/account_manager.h
+++ b/chromeos/components/account_manager/account_manager.h
@@ -24,6 +24,7 @@
 
 class OAuth2AccessTokenFetcher;
 class OAuth2AccessTokenConsumer;
+class PrefRegistrySimple;
 
 namespace base {
 class SequencedTaskRunner;
@@ -117,6 +118,8 @@
   AccountManager();
   virtual ~AccountManager();
 
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
   // |home_dir| is the path of the Device Account's home directory (root of the
   // user's cryptohome).
   // |request_context| is a non-owning pointer.
diff --git a/chromeos/constants/chromeos_pref_names.cc b/chromeos/constants/chromeos_pref_names.cc
index 2ca159d9..dc0ff875 100644
--- a/chromeos/constants/chromeos_pref_names.cc
+++ b/chromeos/constants/chromeos_pref_names.cc
@@ -46,5 +46,11 @@
 const char kDeviceWiFiFastTransitionEnabled[] =
     "net.device_wifi_fast_transition_enabled";
 
+// A boolean pref to store if Secondary Google Account additions are allowed on
+// Chrome OS Account Manager. The default value is |true|, i.e. Secondary Google
+// Account additions are allowed by default.
+const char kSecondaryGoogleAccountSigninAllowed[] =
+    "account_manager.secondary_google_account_signin_allowed";
+
 }  // namespace prefs
 }  // namespace chromeos
diff --git a/chromeos/constants/chromeos_pref_names.h b/chromeos/constants/chromeos_pref_names.h
index 181ea3f..717a6cf 100644
--- a/chromeos/constants/chromeos_pref_names.h
+++ b/chromeos/constants/chromeos_pref_names.h
@@ -21,6 +21,8 @@
 extern const char kQuirksClientLastServerCheck[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const char kDeviceWiFiFastTransitionEnabled[];
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const char kSecondaryGoogleAccountSigninAllowed[];
 
 }  // namespace prefs
 }  // namespace chromeos
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index a09cbad..4ab6f83 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -161,8 +161,6 @@
     "fake_sms_client.h",
     "fake_update_engine_client.cc",
     "fake_update_engine_client.h",
-    "fake_upstart_client.cc",
-    "fake_upstart_client.h",
     "fake_virtual_file_provider_client.cc",
     "fake_virtual_file_provider_client.h",
     "gsm_sms_client.cc",
@@ -221,8 +219,10 @@
     "sms_client.h",
     "update_engine_client.cc",
     "update_engine_client.h",
-    "upstart_client.cc",
-    "upstart_client.h",
+    "upstart/fake_upstart_client.cc",
+    "upstart/fake_upstart_client.h",
+    "upstart/upstart_client.cc",
+    "upstart/upstart_client.h",
     "util/account_identifier_operators.cc",
     "util/account_identifier_operators.h",
     "util/tpm_util.cc",
diff --git a/chromeos/dbus/dbus_clients_common.cc b/chromeos/dbus/dbus_clients_common.cc
index 8dca1ee..21907d53 100644
--- a/chromeos/dbus/dbus_clients_common.cc
+++ b/chromeos/dbus/dbus_clients_common.cc
@@ -24,7 +24,6 @@
 #include "chromeos/dbus/fake_shill_service_client.h"
 #include "chromeos/dbus/fake_shill_third_party_vpn_driver_client.h"
 #include "chromeos/dbus/fake_sms_client.h"
-#include "chromeos/dbus/fake_upstart_client.h"
 #include "chromeos/dbus/gsm_sms_client.h"
 #include "chromeos/dbus/machine_learning_client.h"
 #include "chromeos/dbus/modem_messaging_client.h"
@@ -38,7 +37,6 @@
 #include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
 #include "chromeos/dbus/sms_client.h"
 #include "chromeos/dbus/update_engine_client.h"
-#include "chromeos/dbus/upstart_client.h"
 
 namespace chromeos {
 
@@ -109,11 +107,6 @@
     sms_client_.reset(new FakeSMSClient);
 
   update_engine_client_.reset(UpdateEngineClient::Create(client_impl_type));
-
-  if (use_real_clients)
-    upstart_client_.reset(UpstartClient::Create());
-  else
-    upstart_client_.reset(new FakeUpstartClient);
 }
 
 DBusClientsCommon::~DBusClientsCommon() = default;
@@ -138,7 +131,6 @@
   shill_third_party_vpn_driver_client_->Init(system_bus);
   sms_client_->Init(system_bus);
   update_engine_client_->Init(system_bus);
-  upstart_client_->Init(system_bus);
 
   ShillManagerClient::TestInterface* manager =
       shill_manager_client_->GetTestInterface();
diff --git a/chromeos/dbus/dbus_clients_common.h b/chromeos/dbus/dbus_clients_common.h
index 4f313593..69c9f0740 100644
--- a/chromeos/dbus/dbus_clients_common.h
+++ b/chromeos/dbus/dbus_clients_common.h
@@ -33,7 +33,6 @@
 class ShillThirdPartyVpnDriverClient;
 class SMSClient;
 class UpdateEngineClient;
-class UpstartClient;
 
 // D-Bus clients used in multiple processes (e.g. ash, browser, mus).
 class COMPONENT_EXPORT(CHROMEOS_DBUS) DBusClientsCommon {
@@ -68,7 +67,6 @@
   std::unique_ptr<SMSClient> sms_client_;
   std::unique_ptr<SessionManagerClient> session_manager_client_;
   std::unique_ptr<UpdateEngineClient> update_engine_client_;
-  std::unique_ptr<UpstartClient> upstart_client_;
 
   DISALLOW_COPY_AND_ASSIGN(DBusClientsCommon);
 };
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index e47f197..990caad 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -48,7 +48,6 @@
 #include "chromeos/dbus/smb_provider_client.h"
 #include "chromeos/dbus/sms_client.h"
 #include "chromeos/dbus/update_engine_client.h"
-#include "chromeos/dbus/upstart_client.h"
 #include "dbus/bus.h"
 #include "dbus/dbus_statistics.h"
 
@@ -276,10 +275,6 @@
   return clients_common_->update_engine_client_.get();
 }
 
-UpstartClient* DBusThreadManager::GetUpstartClient() {
-  return clients_common_ ? clients_common_->upstart_client_.get() : nullptr;
-}
-
 VirtualFileProviderClient* DBusThreadManager::GetVirtualFileProviderClient() {
   return clients_browser_
              ? clients_browser_->virtual_file_provider_client_.get()
@@ -505,10 +500,4 @@
       std::move(client);
 }
 
-void DBusThreadManagerSetter::SetUpstartClient(
-    std::unique_ptr<UpstartClient> client) {
-  DBusThreadManager::Get()->clients_common_->upstart_client_ =
-      std::move(client);
-}
-
 }  // namespace chromeos
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 3dbbbdb1..25de2103 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -63,7 +63,6 @@
 class SmbProviderClient;
 class SMSClient;
 class UpdateEngineClient;
-class UpstartClient;
 class VirtualFileProviderClient;
 
 // DBusThreadManager manages the D-Bus thread, the thread dedicated to
@@ -169,7 +168,6 @@
   SmbProviderClient* GetSmbProviderClient();
   SMSClient* GetSMSClient();
   UpdateEngineClient* GetUpdateEngineClient();
-  UpstartClient* GetUpstartClient();
   VirtualFileProviderClient* GetVirtualFileProviderClient();
 
  private:
@@ -229,7 +227,6 @@
       std::unique_ptr<ShillThirdPartyVpnDriverClient> client);
   void SetSmbProviderClient(std::unique_ptr<SmbProviderClient> client);
   void SetUpdateEngineClient(std::unique_ptr<UpdateEngineClient> client);
-  void SetUpstartClient(std::unique_ptr<UpstartClient> client);
 
  private:
   friend class DBusThreadManager;
diff --git a/chromeos/dbus/fake_upstart_client.cc b/chromeos/dbus/upstart/fake_upstart_client.cc
similarity index 87%
rename from chromeos/dbus/fake_upstart_client.cc
rename to chromeos/dbus/upstart/fake_upstart_client.cc
index 056a9bb..43bebce 100644
--- a/chromeos/dbus/fake_upstart_client.cc
+++ b/chromeos/dbus/upstart/fake_upstart_client.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_upstart_client.h"
+#include "chromeos/dbus/upstart/fake_upstart_client.h"
 
 #include "base/bind.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -12,11 +12,25 @@
 
 namespace chromeos {
 
-FakeUpstartClient::FakeUpstartClient() = default;
+namespace {
+// Used to track the fake instance, mirrors the instance in the base class.
+FakeUpstartClient* g_instance = nullptr;
+}  // namespace
 
-FakeUpstartClient::~FakeUpstartClient() = default;
+FakeUpstartClient::FakeUpstartClient() {
+  DCHECK(!g_instance);
+  g_instance = this;
+}
 
-void FakeUpstartClient::Init(dbus::Bus* bus) {}
+FakeUpstartClient::~FakeUpstartClient() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+// static
+FakeUpstartClient* FakeUpstartClient::Get() {
+  return g_instance;
+}
 
 void FakeUpstartClient::StartJob(const std::string& job,
                                  const std::vector<std::string>& upstart_env,
diff --git a/chromeos/dbus/fake_upstart_client.h b/chromeos/dbus/upstart/fake_upstart_client.h
similarity index 78%
rename from chromeos/dbus/fake_upstart_client.h
rename to chromeos/dbus/upstart/fake_upstart_client.h
index 0c4bfb8..6501997 100644
--- a/chromeos/dbus/fake_upstart_client.h
+++ b/chromeos/dbus/upstart/fake_upstart_client.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_FAKE_UPSTART_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_UPSTART_CLIENT_H_
+#ifndef CHROMEOS_DBUS_UPSTART_FAKE_UPSTART_CLIENT_H_
+#define CHROMEOS_DBUS_UPSTART_FAKE_UPSTART_CLIENT_H_
 
 #include "base/macros.h"
 
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 
 namespace chromeos {
 
@@ -16,8 +16,8 @@
   FakeUpstartClient();
   ~FakeUpstartClient() override;
 
-  // DBusClient overrides.
-  void Init(dbus::Bus* bus) override;
+  // Returns the fake global instance if initialized. May return null.
+  static FakeUpstartClient* Get();
 
   // UpstartClient overrides:
   void StartJob(const std::string& job,
@@ -39,4 +39,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_UPSTART_CLIENT_H_
+#endif  // CHROMEOS_DBUS_UPSTART_FAKE_UPSTART_CLIENT_H_
diff --git a/chromeos/dbus/upstart_client.cc b/chromeos/dbus/upstart/upstart_client.cc
similarity index 79%
rename from chromeos/dbus/upstart_client.cc
rename to chromeos/dbus/upstart/upstart_client.cc
index 31de8f6d..b7de8ab 100644
--- a/chromeos/dbus/upstart_client.cc
+++ b/chromeos/dbus/upstart/upstart_client.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/dbus/upstart/fake_upstart_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_proxy.h"
@@ -24,9 +25,12 @@
 constexpr char kAuthPolicyJob[] = "authpolicyd";
 constexpr char kMediaAnalyticsJob[] = "rtanalytics";
 
+UpstartClient* g_instance = nullptr;
+
 class UpstartClientImpl : public UpstartClient {
  public:
-  UpstartClientImpl() : weak_ptr_factory_(this) {}
+  explicit UpstartClientImpl(dbus::Bus* bus)
+      : bus_(bus), weak_ptr_factory_(this) {}
 
   ~UpstartClientImpl() override = default;
 
@@ -67,10 +71,6 @@
   void StopMediaAnalytics(VoidDBusMethodCallback callback) override {
     StopJob(kMediaAnalyticsJob, std::move(callback));
   }
- protected:
-  void Init(dbus::Bus* bus) override {
-    bus_ = bus;
-  }
 
  private:
   void CallJobMethod(const std::string& job,
@@ -104,13 +104,39 @@
 
 }  // namespace
 
-UpstartClient::UpstartClient() = default;
+UpstartClient::UpstartClient() {
+  DCHECK(!g_instance);
+  g_instance = this;
+}
 
-UpstartClient::~UpstartClient() = default;
+UpstartClient::~UpstartClient() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
 
 // static
-UpstartClient* UpstartClient::Create() {
-  return new UpstartClientImpl();
+void UpstartClient::Initialize(dbus::Bus* bus) {
+  DCHECK(bus);
+  new UpstartClientImpl(bus);
+}
+
+// static
+void UpstartClient::InitializeFake() {
+  // Do not create a new fake if it was initialized early in a browser test (to
+  // allow test properties to be set).
+  if (!FakeUpstartClient::Get())
+    new FakeUpstartClient();
+}
+
+// static
+void UpstartClient::Shutdown() {
+  DCHECK(g_instance);
+  delete g_instance;
+}
+
+// static
+UpstartClient* UpstartClient::Get() {
+  return g_instance;
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/upstart_client.h b/chromeos/dbus/upstart/upstart_client.h
similarity index 74%
rename from chromeos/dbus/upstart_client.h
rename to chromeos/dbus/upstart/upstart_client.h
index 8449b235..48eb2cd 100644
--- a/chromeos/dbus/upstart_client.h
+++ b/chromeos/dbus/upstart/upstart_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_UPSTART_CLIENT_H_
-#define CHROMEOS_DBUS_UPSTART_CLIENT_H_
+#ifndef CHROMEOS_DBUS_UPSTART_UPSTART_CLIENT_H_
+#define CHROMEOS_DBUS_UPSTART_UPSTART_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -11,21 +11,32 @@
 #include "base/callback.h"
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 
+namespace dbus {
+class Bus;
+}
+
 namespace chromeos {
 
 // UpstartClient is used to communicate with the com.ubuntu.Upstart
 // sevice. All methods should be called from the origin thread (UI thread) which
 // initializes the DBusThreadManager instance.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) UpstartClient : public DBusClient {
+class COMPONENT_EXPORT(CHROMEOS_DBUS) UpstartClient {
  public:
-  ~UpstartClient() override;
+  virtual ~UpstartClient();
 
-  // Factory function, creates a new instance and returns ownership.
-  // For normal usage, access the singleton via DBusThreadManager::Get().
-  static UpstartClient* Create();
+  // Creates and initializes the global instance. |bus| must not be null.
+  static void Initialize(dbus::Bus* bus);
+
+  // Creates and initializes a fake global instance if not already created.
+  static void InitializeFake();
+
+  // Destroys the global instance which must have been initialized.
+  static void Shutdown();
+
+  // Returns the global instance if initialized. May return null.
+  static UpstartClient* Get();
 
   // Starts an Upstart job.
   // |job|: Name of Upstart job.
@@ -62,8 +73,9 @@
 
   // Provides an interface for stopping the media analytics process.
   virtual void StopMediaAnalytics(VoidDBusMethodCallback callback) = 0;
+
  protected:
-  // Create() should be used instead.
+  // Initialize() should be used instead.
   UpstartClient();
 
  private:
@@ -72,4 +84,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_UPSTART_CLIENT_H_
+#endif  // CHROMEOS_DBUS_UPSTART_UPSTART_CLIENT_H_
diff --git a/chromeos/login/auth/authpolicy_login_helper.cc b/chromeos/login/auth/authpolicy_login_helper.cc
index cd96f3c..f577b6e 100644
--- a/chromeos/login/auth/authpolicy_login_helper.cc
+++ b/chromeos/login/auth/authpolicy_login_helper.cc
@@ -12,7 +12,7 @@
 #include "base/task/post_task.h"
 #include "chromeos/dbus/auth_policy_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/dbus/util/tpm_util.h"
 #include "crypto/encryptor.h"
 #include "crypto/hmac.h"
@@ -153,9 +153,7 @@
 
 // static
 void AuthPolicyLoginHelper::Restart() {
-  chromeos::DBusThreadManager::Get()
-      ->GetUpstartClient()
-      ->RestartAuthPolicyService();
+  chromeos::UpstartClient::Get()->RestartAuthPolicyService();
 }
 
 // static
diff --git a/components/arc/arc_data_remover.cc b/components/arc/arc_data_remover.cc
index 8f80aa8..99a2e62 100644
--- a/components/arc/arc_data_remover.cc
+++ b/components/arc/arc_data_remover.cc
@@ -9,8 +9,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/logging.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/arc/arc_prefs.h"
 
 namespace arc {
@@ -46,8 +45,12 @@
   }
 
   VLOG(1) << "Starting ARC data removal";
-  auto* upstart_client = chromeos::DBusThreadManager::Get()->GetUpstartClient();
-  DCHECK(upstart_client);
+  auto* upstart_client = chromeos::UpstartClient::Get();
+  if (!upstart_client) {
+    // May be null in tests
+    std::move(callback).Run(base::nullopt);
+    return;
+  }
   const std::string account_id =
       cryptohome::CreateAccountIdentifierFromIdentification(cryptohome_id_)
           .account_id();
diff --git a/components/arc/arc_data_remover_unittest.cc b/components/arc/arc_data_remover_unittest.cc
index 13873a5..4e825f58 100644
--- a/components/arc/arc_data_remover_unittest.cc
+++ b/components/arc/arc_data_remover_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_upstart_client.h"
+#include "chromeos/dbus/upstart/fake_upstart_client.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/arc_prefs.h"
 #include "components/prefs/testing_pref_service.h"
@@ -46,14 +46,15 @@
   ArcDataRemoverTest() = default;
 
   void SetUp() override {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetUpstartClient(
-        std::make_unique<TestUpstartClient>());
     chromeos::DBusThreadManager::Initialize();
-
+    test_upstart_client_ = std::make_unique<TestUpstartClient>();
     prefs::RegisterProfilePrefs(prefs_.registry());
   }
 
-  void TearDown() override { chromeos::DBusThreadManager::Shutdown(); }
+  void TearDown() override {
+    test_upstart_client_.reset();
+    chromeos::DBusThreadManager::Shutdown();
+  }
 
   PrefService* prefs() { return &prefs_; }
 
@@ -62,15 +63,14 @@
   }
 
   TestUpstartClient* upstart_client() {
-    return static_cast<TestUpstartClient*>(
-        chromeos::DBusThreadManager::Get()->GetUpstartClient());
+    return static_cast<TestUpstartClient*>(chromeos::UpstartClient::Get());
   }
 
  private:
   TestingPrefServiceSimple prefs_;
   const cryptohome::Identification cryptohome_id_{EmptyAccountId()};
-
   base::test::ScopedTaskEnvironment scoped_task_environment_;
+  std::unique_ptr<TestUpstartClient> test_upstart_client_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcDataRemoverTest);
 };
diff --git a/components/arc/arc_vm_client_adapter.cc b/components/arc/arc_vm_client_adapter.cc
index 5aaec266..fc795c59 100644
--- a/components/arc/arc_vm_client_adapter.cc
+++ b/components/arc/arc_vm_client_adapter.cc
@@ -13,9 +13,8 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/post_task.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 
 namespace arc {
 
@@ -54,8 +53,7 @@
     // TODO(yusukes): Consider doing the same as crostini rather than taking to
     // Upstart.
     VLOG(1) << "Starting arcvm";
-    auto* upstart_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
+    auto* upstart_client = chromeos::UpstartClient::Get();
     DCHECK(upstart_client);
     upstart_client->StartJob(
         kArcVmUpstartJob,
@@ -72,8 +70,7 @@
     // TODO(yusukes): Consider doing the same as crostini rather than taking to
     // Upstart.
     VLOG(1) << "Stopping arcvm";
-    auto* upstart_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
+    auto* upstart_client = chromeos::UpstartClient::Get();
     DCHECK(upstart_client);
     upstart_client->StopJob(
         kArcVmUpstartJob,
diff --git a/components/autofill/android/BUILD.gn b/components/autofill/android/BUILD.gn
index bd2ac36..9540e8a 100644
--- a/components/autofill/android/BUILD.gn
+++ b/components/autofill/android/BUILD.gn
@@ -107,7 +107,7 @@
   deps = [
     "//base:base_java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   java_files = [
     "java/src/org/chromium/components/autofill/AutofillProvider.java",
diff --git a/components/autofill/core/browser/payments/payments_client.cc b/components/autofill/core/browser/payments/payments_client.cc
index 2a1c5eaf..eb228c3 100644
--- a/components/autofill/core/browser/payments/payments_client.cc
+++ b/components/autofill/core/browser/payments/payments_client.cc
@@ -91,32 +91,6 @@
   return GetBaseSecureUrl().Resolve(path);
 }
 
-// Tries to get the string |out_value| from the |dictionary| with the given
-// |key|.
-// Returns true if the string value was found, false otherwise.
-bool TryGetString(std::string key,
-                  base::Value& dictionary,
-                  std::string* out_value) {
-  base::Value* str_ptr = dictionary.FindKey(key);
-  if (str_ptr) {
-    *out_value = str_ptr->GetString();
-  }
-  return str_ptr;
-}
-
-// Tries to get the string |out_value| from the |dictionary| with the given
-// |path|.
-// Returns true if the string value was found, false otherwise.
-bool TryGetStringByPath(std::initializer_list<base::StringPiece> path,
-                        base::Value& dictionary,
-                        std::string* out_value) {
-  base::Value* str_ptr = dictionary.FindPath(path);
-  if (str_ptr) {
-    *out_value = str_ptr->GetString();
-  }
-  return str_ptr;
-}
-
 base::Value BuildCustomerContextDictionary(int64_t external_customer_id) {
   base::Value customer_context(base::Value::Type::DICTIONARY);
   customer_context.SetKey("external_customer_id",
@@ -314,8 +288,9 @@
     return request_content;
   }
 
-  void ParseResponse(base::Value response) override {
-    TryGetString("pan", response, &real_pan_);
+  void ParseResponse(const base::Value& response) override {
+    const auto* pan = response.FindStringKey("pan");
+    real_pan_ = pan ? *pan : std::string();
   }
 
   bool IsResponseComplete() override { return !real_pan_.empty(); }
@@ -331,6 +306,8 @@
                           const std::string&)>
       callback_;
   std::string real_pan_;
+
+  DISALLOW_COPY_AND_ASSIGN(UnmaskCardRequest);
 };
 
 class GetUploadDetailsRequest : public PaymentsRequest {
@@ -434,22 +411,23 @@
     return request_content;
   }
 
-  void ParseResponse(base::Value response) override {
-    std::string context_token_utf8;
-    if (TryGetString("context_token", response, &context_token_utf8)) {
-      context_token_ = base::UTF8ToUTF16(context_token_utf8);
-    }
+  void ParseResponse(const base::Value& response) override {
+    const auto* context_token = response.FindStringKey("context_token");
+    context_token_ =
+        context_token ? base::UTF8ToUTF16(*context_token) : base::string16();
 
-    base::Value* dictionary_value = response.FindKey("legal_message");
+    const base::Value* dictionary_value =
+        response.FindKeyOfType("legal_message", base::Value::Type::DICTIONARY);
     if (dictionary_value)
       legal_message_ = std::make_unique<base::Value>(dictionary_value->Clone());
 
-    base::Value* list_ptr = response.FindKey("supported_card_bin_ranges");
-    if (list_ptr && list_ptr->is_list()) {
-      for (base::Value& result : list_ptr->GetList()) {
+    const base::Value* list_ptr = response.FindKeyOfType(
+        "supported_card_bin_ranges", base::Value::Type::LIST);
+    if (list_ptr) {
+      for (const base::Value& result : list_ptr->GetList()) {
         DCHECK(result.is_dict());
-        base::Optional<int> start = response.FindIntKey("start");
-        base::Optional<int> end = response.FindIntKey("end");
+        base::Optional<int> start = result.FindIntKey("start");
+        base::Optional<int> end = result.FindIntKey("end");
         supported_card_bin_ranges_.push_back(std::make_pair(*start, *end));
       }
     }
@@ -480,6 +458,8 @@
   std::vector<std::pair<int, int>> supported_card_bin_ranges_;
   const int billable_service_number_;
   PaymentsClient::UploadCardSource upload_card_source_;
+
+  DISALLOW_COPY_AND_ASSIGN(GetUploadDetailsRequest);
 };
 
 class UploadCardRequest : public PaymentsRequest {
@@ -575,8 +555,10 @@
     return request_content;
   }
 
-  void ParseResponse(base::Value response) override {
-    TryGetString("credit_card_id", response, &server_id_);
+  void ParseResponse(const base::Value& response) override {
+    const std::string* credit_card_id =
+        response.FindStringKey("credit_card_id");
+    server_id_ = credit_card_id ? *credit_card_id : std::string();
   }
 
   bool IsResponseComplete() override { return true; }
@@ -592,6 +574,8 @@
                           const std::string&)>
       callback_;
   std::string server_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(UploadCardRequest);
 };
 
 class MigrateCardsRequest : public PaymentsRequest {
@@ -666,26 +650,27 @@
     return request_content;
   }
 
-  void ParseResponse(base::Value response) override {
-    base::Value* list_ptr = response.FindKey("save_result");
-    if (!list_ptr || !list_ptr->is_list())
+  void ParseResponse(const base::Value& response) override {
+    const auto* found_list =
+        response.FindKeyOfType("save_result", base::Value::Type::LIST);
+    if (!found_list)
       return;
+
     save_result_ =
         std::make_unique<std::unordered_map<std::string, std::string>>();
-
-    for (base::Value& result : list_ptr->GetList()) {
+    for (const base::Value& result : found_list->GetList()) {
       if (result.is_dict()) {
-        std::string unique_id;
-        TryGetString("unique_id", result, &unique_id);
-
-        std::string save_result;
-        TryGetString("status", result, &save_result);
-
-        save_result_->insert(std::make_pair(unique_id, save_result));
+        const std::string* unique_id = result.FindStringKey("unique_id");
+        const std::string* status = result.FindStringKey("status");
+        save_result_->insert(
+            std::make_pair(unique_id ? *unique_id : std::string(),
+                           status ? *status : std::string()));
       }
     }
 
-    TryGetString("value_prop_display_text", response, &display_text_);
+    const std::string* display_text =
+        response.FindStringKey("value_prop_display_text");
+    display_text_ = display_text ? *display_text : std::string();
   }
 
   bool IsResponseComplete() override {
@@ -720,6 +705,8 @@
   MigrateCardsCallback callback_;
   std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
   std::string display_text_;
+
+  DISALLOW_COPY_AND_ASSIGN(MigrateCardsRequest);
 };
 
 }  // namespace
@@ -895,8 +882,11 @@
       std::string error_code;
       base::Optional<base::Value> message_value = base::JSONReader::Read(data);
       if (message_value && message_value->is_dict()) {
-        TryGetStringByPath({"error", "code"}, *message_value, &error_code);
-        request_->ParseResponse(*std::move(message_value));
+        const auto* found = message_value->FindPathOfType(
+            {"error", "code"}, base::Value::Type::STRING);
+        if (found)
+          error_code = found->GetString();
+        request_->ParseResponse(*message_value);
       }
 
       if (base::LowerCaseEqualsASCII(error_code, "internal"))
diff --git a/components/autofill/core/browser/payments/payments_request.h b/components/autofill/core/browser/payments/payments_request.h
index e71d554..61916ad8 100644
--- a/components/autofill/core/browser/payments/payments_request.h
+++ b/components/autofill/core/browser/payments/payments_request.h
@@ -28,7 +28,7 @@
   virtual std::string GetRequestContent() = 0;
 
   // Parses the required elements of the HTTP response.
-  virtual void ParseResponse(base::Value response) = 0;
+  virtual void ParseResponse(const base::Value& response) = 0;
 
   // Returns true if all of the required elements were successfully retrieved by
   // a call to ParseResponse.
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
index 55d0a8a..ef98a6c 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -11,6 +11,7 @@
 
 #include "base/base64.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/pickle.h"
 #include "components/autofill/core/browser/autofill_metadata.h"
@@ -20,6 +21,7 @@
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_util.h"
 #include "components/sync/model/entity_data.h"
 #include "components/sync/model/mutable_data_batch.h"
@@ -445,10 +447,22 @@
   for (const auto& it : addresses_metadata) {
     cache_[GetStorageKeyForWalletMetadataTypeAndId(
         WalletMetadataSpecifics::ADDRESS, it.first)] = it.second;
+    UMA_HISTOGRAM_CUSTOM_TIMES(
+        "Autofill.WalletUseDate.Address",
+        /*sample=*/AutofillClock::Now() - it.second.use_date,
+        /*min=*/base::TimeDelta::FromMilliseconds(1),
+        /*max=*/base::TimeDelta::FromDays(365),
+        /*bucket_count=*/50);
   }
   for (const auto& it : cards_metadata) {
     cache_[GetStorageKeyForWalletMetadataTypeAndId(
         WalletMetadataSpecifics::CARD, it.first)] = it.second;
+    UMA_HISTOGRAM_CUSTOM_TIMES(
+        "Autofill.WalletUseDate.Card",
+        /*sample=*/AutofillClock::Now() - it.second.use_date,
+        /*min=*/base::TimeDelta::FromMilliseconds(1),
+        /*max=*/base::TimeDelta::FromDays(365),
+        /*bucket_count=*/50);
   }
 
   // Load the metadata and send to the processor.
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
index 7b88c1b8..df3a251 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -13,6 +13,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
 #include "components/autofill/core/browser/autofill_data_model.h"
@@ -22,6 +23,7 @@
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_util.h"
 #include "components/sync/model/sync_change.h"
 #include "components/sync/model/sync_change_processor.h"
@@ -383,6 +385,33 @@
     result = MergeData(initial_sync_data);
   }
 
+  // Record ages for individual metadata entities to UMA.
+  for (const syncer::SyncData& data : cache_) {
+    const sync_pb::WalletMetadataSpecifics& specifics =
+        data.GetSpecifics().wallet_metadata();
+    base::Time use_date = base::Time::FromDeltaSinceWindowsEpoch(
+        base::TimeDelta::FromMicroseconds(specifics.use_date()));
+    switch (specifics.type()) {
+      case sync_pb::WalletMetadataSpecifics::ADDRESS:
+        UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.WalletUseDate.Address",
+                                   /*sample=*/AutofillClock::Now() - use_date,
+                                   /*min=*/base::TimeDelta::FromMilliseconds(1),
+                                   /*max=*/base::TimeDelta::FromDays(365),
+                                   /*bucket_count=*/50);
+        break;
+      case sync_pb::WalletMetadataSpecifics::CARD:
+        UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.WalletUseDate.Card",
+                                   /*sample=*/AutofillClock::Now() - use_date,
+                                   /*min=*/base::TimeDelta::FromMilliseconds(1),
+                                   /*max=*/base::TimeDelta::FromDays(365),
+                                   /*bucket_count=*/50);
+        break;
+      case sync_pb::WalletMetadataSpecifics::UNKNOWN:
+        NOTREACHED();
+        break;
+    }
+  }
+
   // Notify that sync has started. This callback does not currently take into
   // account whether we're actually tracking wallet data.
   if (web_data_backend_)
diff --git a/components/background_task_scheduler/BUILD.gn b/components/background_task_scheduler/BUILD.gn
index dea0bb6c..e89bd9d4 100644
--- a/components/background_task_scheduler/BUILD.gn
+++ b/components/background_task_scheduler/BUILD.gn
@@ -56,7 +56,7 @@
       "$google_play_services_package:google_play_services_gcm_java",
       "$google_play_services_package:google_play_services_tasks_java",
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 
diff --git a/components/bookmarks/common/android/BUILD.gn b/components/bookmarks/common/android/BUILD.gn
index b53aeb5..4ac9ad97 100644
--- a/components/bookmarks/common/android/BUILD.gn
+++ b/components/bookmarks/common/android/BUILD.gn
@@ -19,7 +19,7 @@
 android_library("bookmarks_java") {
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   srcjar_deps = [ ":bookmark_type_javagen" ]
   java_files = [ "java/src/org/chromium/components/bookmarks/BookmarkId.java" ]
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index e21e8b98..fff8f1dc 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -255,7 +255,7 @@
 
   deps = [
     ":api_version",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
 }
 
@@ -295,7 +295,7 @@
   deps = [
     ":cronet_api_java",
     ":impl_version",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   deps += cronet_impl_common_java_deps_to_package
 
@@ -316,7 +316,7 @@
     ":cronet_api_java",
     ":cronet_impl_common_base_java",
     "//net/android:net_thread_stats_uid_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/jsr-305:jsr_305_javalib",
   ]
 }
@@ -373,7 +373,7 @@
   deps = [
     ":cronet_api_java",
     ":cronet_impl_common_base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/jsr-305:jsr_305_javalib",
   ]
   deps += cronet_impl_native_java_deps_to_package
diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn
index 5963bee..26a6dd0 100644
--- a/components/download/public/common/BUILD.gn
+++ b/components/download/public/common/BUILD.gn
@@ -97,7 +97,7 @@
 
     deps = [
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 
diff --git a/components/download/public/task/BUILD.gn b/components/download/public/task/BUILD.gn
index 4a53aa09..f98a9b2 100644
--- a/components/download/public/task/BUILD.gn
+++ b/components/download/public/task/BUILD.gn
@@ -30,7 +30,7 @@
 
     deps = [
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 
diff --git a/components/embedder_support/android/BUILD.gn b/components/embedder_support/android/BUILD.gn
index 7eb08dc7..5d300e8 100644
--- a/components/embedder_support/android/BUILD.gn
+++ b/components/embedder_support/android/BUILD.gn
@@ -149,7 +149,7 @@
     ":web_contents_delegate_java_resources",
     "//base:base_java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:android_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
     "//ui/android:ui_java",
   ]
   java_files = [
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 6d72d41..6b29b75 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -944,10 +944,11 @@
   viz::SharedQuadState* quad_state =
       render_pass->CreateAndAppendSharedQuadState();
   quad_state->SetAll(
-      quad_to_target_transform, quad_rect /* quad_layer_rect */,
-      quad_rect /* visible_quad_layer_rect */, gfx::Rect() /* clip_rect */,
-      false /* is_clipped */, are_contents_opaque, state_.alpha /* opacity */,
-      SkBlendMode::kSrcOver /* blend_mode */, 0 /* sorting_context_id */);
+      quad_to_target_transform, quad_rect /*quad_layer_rect=*/,
+      quad_rect /*visible_quad_layer_rect=*/,
+      gfx::RRectF() /*rounded_corner_bounds=*/, gfx::Rect() /*clip_rect=*/,
+      false /*is_clipped=*/, are_contents_opaque, state_.alpha /*opacity=*/,
+      SkBlendMode::kSrcOver /*blend_mode=*/, 0 /*sorting_context_id=*/);
 
   if (current_resource_.id) {
     gfx::RectF uv_crop(gfx::SizeF(1, 1));
diff --git a/components/feature_engagement/internal/BUILD.gn b/components/feature_engagement/internal/BUILD.gn
index 9c056121..498369dd 100644
--- a/components/feature_engagement/internal/BUILD.gn
+++ b/components/feature_engagement/internal/BUILD.gn
@@ -141,7 +141,7 @@
     deps = [
       "//base:base_java",
       "//components/feature_engagement/public:public_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 
diff --git a/components/feature_engagement/public/BUILD.gn b/components/feature_engagement/public/BUILD.gn
index 95861e7..d5d000c 100644
--- a/components/feature_engagement/public/BUILD.gn
+++ b/components/feature_engagement/public/BUILD.gn
@@ -39,7 +39,7 @@
 
     deps = [
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
 
     srcjar_deps = [ ":public_java_enums_srcjar" ]
diff --git a/components/gwp_asan/client/guarded_page_allocator.cc b/components/gwp_asan/client/guarded_page_allocator.cc
index dbbf43a..63e99f8 100644
--- a/components/gwp_asan/client/guarded_page_allocator.cc
+++ b/components/gwp_asan/client/guarded_page_allocator.cc
@@ -5,7 +5,6 @@
 #include "components/gwp_asan/client/guarded_page_allocator.h"
 
 #include <algorithm>
-#include <iterator>
 #include <memory>
 
 #include "base/bits.h"
@@ -97,8 +96,9 @@
   CHECK(base::bits::IsPowerOfTwo(align));
 
   AllocatorState::SlotIdx free_slot;
-  if (!ReserveSlot(&free_slot))
-    return nullptr;  // All slots are reserved.
+  AllocatorState::MetadataIdx free_metadata;
+  if (!ReserveSlotAndMetadata(&free_slot, &free_metadata))
+    return nullptr;
 
   uintptr_t free_page = state_.SlotToAddr(free_slot);
   MarkPageReadWrite(reinterpret_cast<void*>(free_page));
@@ -114,7 +114,7 @@
   void* alloc = reinterpret_cast<void*>(free_page + offset);
 
   // Initialize slot metadata.
-  RecordAllocationMetadata(free_slot, size, alloc);
+  RecordAllocationMetadata(free_metadata, size, alloc);
 
   return alloc;
 }
@@ -124,16 +124,17 @@
 
   const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
   AllocatorState::SlotIdx slot = state_.AddrToSlot(state_.GetPageAddr(addr));
+  AllocatorState::MetadataIdx metadata_idx = slot;
 
   // Check for a call to free() with an incorrect pointer (e.g. the pointer does
   // not match the allocated pointer.)
-  if (addr != metadata_[slot].alloc_ptr) {
+  if (addr != metadata_[metadata_idx].alloc_ptr) {
     state_.free_invalid_address = addr;
     __builtin_trap();
   }
 
   // Check for double free.
-  if (metadata_[slot].deallocation_occurred.exchange(true)) {
+  if (metadata_[metadata_idx].deallocation_occurred.exchange(true)) {
     state_.double_free_address = addr;
     // TODO(https://crbug.com/925447): The other thread may not be done writing
     // a stack trace so we could spin here until it's read; however, it's also
@@ -145,27 +146,29 @@
 
   // Record deallocation stack trace/thread id before marking the page
   // inaccessible in case a use-after-free occurs immediately.
-  RecordDeallocationMetadata(slot);
+  RecordDeallocationMetadata(metadata_idx);
   MarkPageInaccessible(reinterpret_cast<void*>(state_.GetPageAddr(addr)));
 
-  FreeSlot(slot);
+  FreeSlotAndMetadata(slot, metadata_idx);
 }
 
 size_t GuardedPageAllocator::GetRequestedSize(const void* ptr) const {
   CHECK(PointerIsMine(ptr));
   const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
   AllocatorState::SlotIdx slot = state_.AddrToSlot(state_.GetPageAddr(addr));
-  DCHECK_EQ(addr, metadata_[slot].alloc_ptr);
-  return metadata_[slot].alloc_size;
+  AllocatorState::MetadataIdx metadata_idx = slot;
+  DCHECK_EQ(addr, metadata_[metadata_idx].alloc_ptr);
+  return metadata_[metadata_idx].alloc_size;
 }
 
 size_t GuardedPageAllocator::RegionSize() const {
   return (2 * state_.total_pages + 1) * state_.page_size;
 }
 
-bool GuardedPageAllocator::ReserveSlot(AllocatorState::SlotIdx* slot) {
+bool GuardedPageAllocator::ReserveSlotAndMetadata(
+    AllocatorState::SlotIdx* slot,
+    AllocatorState::MetadataIdx* metadata_idx) {
   base::AutoLock lock(lock_);
-
   if (num_alloced_pages_ == max_alloced_pages_)
     return false;
   num_alloced_pages_++;
@@ -178,10 +181,15 @@
   free_slots_[rand] = free_slots_[free_slots_end_];
   DCHECK_EQ(free_slots_end_, state_.total_pages - num_alloced_pages_);
 
+  *metadata_idx = *slot;
+
   return true;
 }
 
-void GuardedPageAllocator::FreeSlot(AllocatorState::SlotIdx slot) {
+void GuardedPageAllocator::FreeSlotAndMetadata(
+    AllocatorState::SlotIdx slot,
+    AllocatorState::MetadataIdx metadata_idx) {
+  (void)metadata_idx;
   DCHECK_LT(slot, state_.total_pages);
 
   base::AutoLock lock(lock_);
@@ -196,39 +204,39 @@
 }
 
 void GuardedPageAllocator::RecordAllocationMetadata(
-    AllocatorState::SlotIdx slot,
+    AllocatorState::MetadataIdx metadata_idx,
     size_t size,
     void* ptr) {
-  metadata_[slot].alloc_size = size;
-  metadata_[slot].alloc_ptr = reinterpret_cast<uintptr_t>(ptr);
+  metadata_[metadata_idx].alloc_size = size;
+  metadata_[metadata_idx].alloc_ptr = reinterpret_cast<uintptr_t>(ptr);
 
   void* trace[AllocatorState::kMaxStackFrames];
   size_t len =
       base::debug::CollectStackTrace(trace, AllocatorState::kMaxStackFrames);
-  metadata_[slot].alloc.trace_len =
+  metadata_[metadata_idx].alloc.trace_len =
       Pack(reinterpret_cast<uintptr_t*>(trace), len,
-           metadata_[slot].alloc.packed_trace,
-           sizeof(metadata_[slot].alloc.packed_trace));
-  metadata_[slot].alloc.tid = ReportTid();
-  metadata_[slot].alloc.trace_collected = true;
+           metadata_[metadata_idx].alloc.packed_trace,
+           sizeof(metadata_[metadata_idx].alloc.packed_trace));
+  metadata_[metadata_idx].alloc.tid = ReportTid();
+  metadata_[metadata_idx].alloc.trace_collected = true;
 
-  metadata_[slot].dealloc.tid = base::kInvalidThreadId;
-  metadata_[slot].dealloc.trace_len = 0;
-  metadata_[slot].dealloc.trace_collected = false;
-  metadata_[slot].deallocation_occurred = false;
+  metadata_[metadata_idx].dealloc.tid = base::kInvalidThreadId;
+  metadata_[metadata_idx].dealloc.trace_len = 0;
+  metadata_[metadata_idx].dealloc.trace_collected = false;
+  metadata_[metadata_idx].deallocation_occurred = false;
 }
 
 void GuardedPageAllocator::RecordDeallocationMetadata(
-    AllocatorState::SlotIdx slot) {
+    AllocatorState::MetadataIdx metadata_idx) {
   void* trace[AllocatorState::kMaxStackFrames];
   size_t len =
       base::debug::CollectStackTrace(trace, AllocatorState::kMaxStackFrames);
-  metadata_[slot].dealloc.trace_len =
+  metadata_[metadata_idx].dealloc.trace_len =
       Pack(reinterpret_cast<uintptr_t*>(trace), len,
-           metadata_[slot].dealloc.packed_trace,
-           sizeof(metadata_[slot].dealloc.packed_trace));
-  metadata_[slot].dealloc.tid = ReportTid();
-  metadata_[slot].dealloc.trace_collected = true;
+           metadata_[metadata_idx].dealloc.packed_trace,
+           sizeof(metadata_[metadata_idx].dealloc.packed_trace));
+  metadata_[metadata_idx].dealloc.tid = ReportTid();
+  metadata_[metadata_idx].dealloc.trace_collected = true;
 }
 
 uintptr_t GuardedPageAllocator::GetCrashKeyAddress() const {
diff --git a/components/gwp_asan/client/guarded_page_allocator.h b/components/gwp_asan/client/guarded_page_allocator.h
index 4f33026..d820079 100644
--- a/components/gwp_asan/client/guarded_page_allocator.h
+++ b/components/gwp_asan/client/guarded_page_allocator.h
@@ -44,9 +44,7 @@
   // It must be less than or equal to the allocation size. If it's left as zero
   // it will default to the default alignment the allocator chooses.
   //
-  // Preconditions: Init() must have been called,
-  //                size <= page_size,
-  //                align <= page_size
+  // Preconditions: Init() must have been called.
   void* Allocate(size_t size, size_t align = 0);
 
   // Deallocates memory pointed to by ptr. ptr must have been previously
@@ -54,7 +52,7 @@
   void Deallocate(void* ptr);
 
   // Returns the size requested when ptr was allocated. ptr must have been
-  // previously returned by a call to Allocate.
+  // previously returned by a call to Allocate, and not have been deallocated.
   size_t GetRequestedSize(const void* ptr) const;
 
   // Get the address of the GuardedPageAllocator crash key (the address of the
@@ -84,21 +82,25 @@
   // used by the quarantine.
   void MarkPageInaccessible(void*);
 
-  // On success, returns true and writes the reserved slot to |slot|.
-  // Otherwise returns false if no slots are available.
-  bool ReserveSlot(AllocatorState::SlotIdx* slot) LOCKS_EXCLUDED(lock_);
+  // On success, returns true and writes the reserved indices to |slot| and
+  // |metadata_idx|. Otherwise returns false if no allocations are available.
+  bool ReserveSlotAndMetadata(AllocatorState::SlotIdx* slot,
+                              AllocatorState::MetadataIdx* metadata_idx)
+      LOCKS_EXCLUDED(lock_);
 
-  // Marks the specified slot as unreserved.
-  void FreeSlot(AllocatorState::SlotIdx slot) LOCKS_EXCLUDED(lock_);
+  // Marks the specified slot and metadata as unreserved.
+  void FreeSlotAndMetadata(AllocatorState::SlotIdx slot,
+                           AllocatorState::MetadataIdx metadata_idx)
+      LOCKS_EXCLUDED(lock_);
 
-  // Record an allocation or deallocation for a given slot index. This
-  // encapsulates the logic for updating the stack traces and metadata for a
-  // given slot.
+  // Record the metadata for an allocation or deallocation for a given metadata
+  // index.
   ALWAYS_INLINE
-  void RecordAllocationMetadata(AllocatorState::SlotIdx slot,
+  void RecordAllocationMetadata(AllocatorState::MetadataIdx metadata_idx,
                                 size_t size,
                                 void* ptr);
-  ALWAYS_INLINE void RecordDeallocationMetadata(AllocatorState::SlotIdx slot);
+  ALWAYS_INLINE void RecordDeallocationMetadata(
+      AllocatorState::MetadataIdx metadata_idx);
 
   // Allocator state shared with with the crash analyzer.
   AllocatorState state_;
diff --git a/components/gwp_asan/common/allocator_state.h b/components/gwp_asan/common/allocator_state.h
index 33ac4e2..7332fec 100644
--- a/components/gwp_asan/common/allocator_state.h
+++ b/components/gwp_asan/common/allocator_state.h
@@ -37,6 +37,7 @@
 
 class AllocatorState {
  public:
+  using MetadataIdx = uint8_t;
   using SlotIdx = uint8_t;
 
   // Maximum number of pages this class can allocate.
diff --git a/components/location/android/BUILD.gn b/components/location/android/BUILD.gn
index 7e5ccfa..736114c5 100644
--- a/components/location/android/BUILD.gn
+++ b/components/location/android/BUILD.gn
@@ -14,7 +14,7 @@
 android_library("location_java") {
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//ui/android:ui_java",
   ]
   java_files =
diff --git a/components/minidump_uploader/BUILD.gn b/components/minidump_uploader/BUILD.gn
index dbf3c437..0d7b0ee 100644
--- a/components/minidump_uploader/BUILD.gn
+++ b/components/minidump_uploader/BUILD.gn
@@ -30,7 +30,7 @@
 android_library("minidump_uploader_java") {
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
 
   java_files = [
diff --git a/components/offline_items_collection/core/BUILD.gn b/components/offline_items_collection/core/BUILD.gn
index e3a5122..917698f4 100644
--- a/components/offline_items_collection/core/BUILD.gn
+++ b/components/offline_items_collection/core/BUILD.gn
@@ -92,7 +92,7 @@
 
     deps = [
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
index 7fae30bb..7e50bfec 100644
--- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -250,8 +250,7 @@
 
   std::unique_ptr<Task> generate_page_bundle_task =
       std::make_unique<GeneratePageBundleTask>(
-          this, service_->GetPrefetchStore(), service_->GetPrefetchGCMHandler(),
-          service_->GetCachedGCMToken(),
+          this, service_->GetPrefetchStore(), service_->GetCachedGCMToken(),
           service_->GetPrefetchNetworkRequestFactory(),
           base::BindOnce(
               &PrefetchDispatcherImpl::DidGenerateBundleOrGetOperationRequest,
diff --git a/components/offline_pages/core/prefetch/prefetch_service.h b/components/offline_pages/core/prefetch/prefetch_service.h
index 0348dc8..96cb7da 100644
--- a/components/offline_pages/core/prefetch/prefetch_service.h
+++ b/components/offline_pages/core/prefetch/prefetch_service.h
@@ -19,6 +19,9 @@
 namespace ntp_snippets {
 class ContentSuggestionsService;
 }
+namespace content {
+class BrowserContext;
+}
 
 namespace offline_pages {
 class OfflineEventLogger;
@@ -82,7 +85,11 @@
   // suggestion from the Prefetching pipeline and/or the Offline Pages database.
   virtual void RemoveSuggestion(GURL url) = 0;
 
-  virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0;
+  // Returns a pointer to the PrefetchGCMHandler, if this is the first time the
+  // function is called, the PrefetchGCMHandler is created using the passed in
+  // context, then returned.
+  virtual PrefetchGCMHandler* GetOrCreatePrefetchGCMHandler(
+      content::BrowserContext* context) = 0;
 
   // Obtains the current GCM token from the PrefetchGCMHandler
   virtual void GetGCMToken(GCMTokenCallback callback) = 0;
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
index 4019ef5..4f6d23b 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -7,10 +7,12 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/offline_pages/core/client_id.h"
 #include "components/offline_pages/core/client_namespace_constants.h"
+#include "components/offline_pages/core/offline_page_feature.h"
 #include "components/offline_pages/core/prefetch/offline_metrics_collector.h"
 #include "components/offline_pages/core/prefetch/prefetch_background_task_handler.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
@@ -28,7 +30,7 @@
 PrefetchServiceImpl::PrefetchServiceImpl(
     std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector,
     std::unique_ptr<PrefetchDispatcher> dispatcher,
-    std::unique_ptr<PrefetchGCMHandler> gcm_handler,
+    CreateGCMHandlerClosure create_gcm_handler_closure,
     std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory,
     OfflinePageModel* offline_page_model,
     std::unique_ptr<PrefetchStore> prefetch_store,
@@ -41,7 +43,7 @@
     image_fetcher::ImageFetcher* thumbnail_image_fetcher)
     : offline_metrics_collector_(std::move(offline_metrics_collector)),
       prefetch_dispatcher_(std::move(dispatcher)),
-      prefetch_gcm_handler_(std::move(gcm_handler)),
+      create_gcm_handler_closure_(std::move(create_gcm_handler_closure)),
       network_request_factory_(std::move(network_request_factory)),
       offline_page_model_(offline_page_model),
       prefetch_store_(std::move(prefetch_store)),
@@ -55,7 +57,6 @@
       weak_ptr_factory_(this) {
   prefetch_dispatcher_->SetService(this);
   prefetch_downloader_->SetPrefetchService(this);
-  prefetch_gcm_handler_->SetService(this);
   if (suggested_articles_observer_)
     suggested_articles_observer_->SetPrefetchService(this);
 }
@@ -67,10 +68,18 @@
 }
 
 void PrefetchServiceImpl::SetCachedGCMToken(const std::string& gcm_token) {
-  gcm_token_ = gcm_token;
+  // This method is passed a cached token that was stored in the job scheduler,
+  // to be used until the PrefetchGCMHandler is created. In some cases, the
+  // PrefetchGCMHandler could have been already created and a fresher token
+  // requested before this function is called. Make sure to not override a
+  // fresher token with a stale one.
+  if (gcm_token_.empty())
+    gcm_token_ = gcm_token;
 }
 
 const std::string& PrefetchServiceImpl::GetCachedGCMToken() const {
+  DCHECK(!gcm_token_.empty()) << "No cached token is set, you should call "
+                                 "PrefetchService::GetGCMToken instead";
   return gcm_token_;
 }
 
@@ -85,7 +94,8 @@
     GCMTokenCallback callback,
     const std::string& gcm_token,
     instance_id::InstanceID::Result result) {
-  // Keep the token fresh
+  // TODO(dimich): Add UMA reporting on instance_id::InstanceID::Result.
+  // Keep the cached token fresh
   gcm_token_ = gcm_token;
   std::move(callback).Run(gcm_token);
 }
@@ -133,7 +143,16 @@
   return prefetch_dispatcher_.get();
 }
 
-PrefetchGCMHandler* PrefetchServiceImpl::GetPrefetchGCMHandler() {
+PrefetchGCMHandler* PrefetchServiceImpl::GetOrCreatePrefetchGCMHandler(
+    content::BrowserContext* context) {
+  if (!prefetch_gcm_handler_) {
+    prefetch_gcm_handler_ = std::move(create_gcm_handler_closure_).Run(context);
+    prefetch_gcm_handler_->SetService(this);
+    if (IsPrefetchingOfflinePagesEnabled()) {
+      // Trigger an update of the cached GCM token.
+      GetGCMToken(base::DoNothing());
+    }
+  }
   return prefetch_gcm_handler_.get();
 }
 
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.h b/components/offline_pages/core/prefetch/prefetch_service_impl.h
index 28a5e144..b036de94 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.h
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.h
@@ -20,12 +20,16 @@
 
 class PrefetchServiceImpl : public PrefetchService {
  public:
+  using CreateGCMHandlerClosure =
+      base::OnceCallback<std::unique_ptr<PrefetchGCMHandler>(
+          content::BrowserContext*)>;
+
   // Zine/Feed: when using Feed, suggested_articles_observer and
   // thumbnail_fetcher should be null. All other parameters must be non-null.
   PrefetchServiceImpl(
       std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector,
       std::unique_ptr<PrefetchDispatcher> dispatcher,
-      std::unique_ptr<PrefetchGCMHandler> gcm_handler,
+      CreateGCMHandlerClosure create_gcm_handler_closure,
       std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory,
       OfflinePageModel* offline_page_model,
       std::unique_ptr<PrefetchStore> prefetch_store,
@@ -46,7 +50,8 @@
       SuggestionsProvider* suggestions_provider) override;
   void NewSuggestionsAvailable() override;
   void RemoveSuggestion(GURL url) override;
-  PrefetchGCMHandler* GetPrefetchGCMHandler() override;
+  PrefetchGCMHandler* GetOrCreatePrefetchGCMHandler(
+      content::BrowserContext* context) override;
   void SetCachedGCMToken(const std::string& gcm_token) override;
   const std::string& GetCachedGCMToken() const override;
   void GetGCMToken(GCMTokenCallback callback) override;
@@ -79,10 +84,11 @@
 
   OfflineEventLogger logger_;
   std::string gcm_token_;
+  std::unique_ptr<PrefetchGCMHandler> prefetch_gcm_handler_;
 
   std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector_;
   std::unique_ptr<PrefetchDispatcher> prefetch_dispatcher_;
-  std::unique_ptr<PrefetchGCMHandler> prefetch_gcm_handler_;
+  CreateGCMHandlerClosure create_gcm_handler_closure_;
   std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory_;
   OfflinePageModel* offline_page_model_;
   std::unique_ptr<PrefetchStore> prefetch_store_;
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
index f19bafe6..46ff427 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
+++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
@@ -194,14 +194,22 @@
 
 void PrefetchServiceTestTaco::CreatePrefetchService() {
   CHECK(!prefetch_service_);
+  auto create_gcm_lambda = [](std::unique_ptr<PrefetchGCMHandler> gcm_handler,
+                              content::BrowserContext* context) {
+    return gcm_handler;
+  };
+  auto gcm_handler_closure =
+      base::BindOnce(create_gcm_lambda, std::move(gcm_handler_));
   prefetch_service_ = std::make_unique<PrefetchServiceImpl>(
       std::move(metrics_collector_), std::move(dispatcher_),
-      std::move(gcm_handler_), std::move(network_request_factory_),
+      std::move(gcm_handler_closure), std::move(network_request_factory_),
       offline_page_model_.get(), std::move(prefetch_store_),
       std::move(suggested_articles_observer_), std::move(prefetch_downloader_),
       std::move(prefetch_importer_),
       std::move(prefetch_background_task_handler_),
       std::move(thumbnail_fetcher_), thumbnail_image_fetcher_.get());
+  // Force create PrefetchGCMHandler
+  prefetch_service_->GetOrCreatePrefetchGCMHandler(nullptr);
 }
 
 std::unique_ptr<PrefetchService>
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.h b/components/offline_pages/core/prefetch/prefetch_service_test_taco.h
index 6ac2da5..d7ae000a 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.h
+++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.h
@@ -16,6 +16,9 @@
 namespace image_fetcher {
 class ImageFetcher;
 }
+namespace content {
+class BrowserContext;
+}
 
 namespace offline_pages {
 class OfflineMetricsCollector;
@@ -109,6 +112,9 @@
   PrefService* pref_service() const { return pref_service_.get(); }
 
  private:
+  std::unique_ptr<PrefetchGCMHandler> GetPrefetchGCMHandler(
+      content::BrowserContext* context);
+
   std::unique_ptr<OfflineMetricsCollector> metrics_collector_;
   std::unique_ptr<PrefetchDispatcher> dispatcher_;
   std::unique_ptr<PrefetchGCMHandler> gcm_handler_;
diff --git a/components/offline_pages/core/prefetch/stub_prefetch_service.cc b/components/offline_pages/core/prefetch/stub_prefetch_service.cc
index f281bda..c6710bf 100644
--- a/components/offline_pages/core/prefetch/stub_prefetch_service.cc
+++ b/components/offline_pages/core/prefetch/stub_prefetch_service.cc
@@ -19,13 +19,15 @@
 void StubPrefetchService::RemoveSuggestion(GURL url) {}
 
 void StubPrefetchService::SetCachedGCMToken(const std::string& gcm_token) {}
+
 void StubPrefetchService::GetGCMToken(GCMTokenCallback callback) {}
 
 const std::string& StubPrefetchService::GetCachedGCMToken() const {
   return gcm_token_;
 }
 
-PrefetchGCMHandler* StubPrefetchService::GetPrefetchGCMHandler() {
+PrefetchGCMHandler* StubPrefetchService::GetOrCreatePrefetchGCMHandler(
+    content::BrowserContext* context) {
   return nullptr;
 }
 
diff --git a/components/offline_pages/core/prefetch/stub_prefetch_service.h b/components/offline_pages/core/prefetch/stub_prefetch_service.h
index 5a5f29f..b8a5fb2 100644
--- a/components/offline_pages/core/prefetch/stub_prefetch_service.h
+++ b/components/offline_pages/core/prefetch/stub_prefetch_service.h
@@ -23,7 +23,8 @@
   void SetCachedGCMToken(const std::string& gcm_token) override;
   const std::string& GetCachedGCMToken() const override;
   void GetGCMToken(GCMTokenCallback callback) override;
-  PrefetchGCMHandler* GetPrefetchGCMHandler() override;
+  PrefetchGCMHandler* GetOrCreatePrefetchGCMHandler(
+      content::BrowserContext* context) override;
   OfflineEventLogger* GetLogger() override;
   OfflineMetricsCollector* GetOfflineMetricsCollector() override;
   PrefetchDispatcher* GetPrefetchDispatcher() override;
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc
index 134e726..871c2ad 100644
--- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc
+++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc
@@ -144,13 +144,11 @@
 GeneratePageBundleTask::GeneratePageBundleTask(
     PrefetchDispatcher* prefetch_dispatcher,
     PrefetchStore* prefetch_store,
-    PrefetchGCMHandler* gcm_handler,
     const std::string& gcm_token,
     PrefetchNetworkRequestFactory* request_factory,
     PrefetchRequestFinishedCallback callback)
     : prefetch_dispatcher_(prefetch_dispatcher),
       prefetch_store_(prefetch_store),
-      gcm_handler_(gcm_handler),
       gcm_token_(gcm_token),
       request_factory_(request_factory),
       callback_(std::move(callback)),
@@ -175,24 +173,7 @@
   DCHECK(!url_and_ids->urls.empty());
   DCHECK_EQ(url_and_ids->urls.size(), url_and_ids->ids.size());
 
-  if (gcm_handler_) {
-    gcm_handler_->GetGCMToken(base::AdaptCallbackForRepeating(
-        base::BindOnce(&GeneratePageBundleTask::GotRegistrationId,
-                       weak_factory_.GetWeakPtr(), std::move(url_and_ids))));
-  } else {
-    DCHECK(!gcm_token_.empty());
-    GotRegistrationId(std::move(url_and_ids), gcm_token_,
-                      instance_id::InstanceID::Result::SUCCESS);
-  }
-}
-
-void GeneratePageBundleTask::GotRegistrationId(
-    std::unique_ptr<UrlAndIds> url_and_ids,
-    const std::string& id,
-    instance_id::InstanceID::Result result) {
-  DCHECK(url_and_ids);
-  // TODO(dimich): Add UMA reporting on instance_id::InstanceID::Result.
-  request_factory_->MakeGeneratePageBundleRequest(url_and_ids->urls, id,
+  request_factory_->MakeGeneratePageBundleRequest(url_and_ids->urls, gcm_token_,
                                                   std::move(callback_));
   prefetch_dispatcher_->GeneratePageBundleRequested(
       std::make_unique<PrefetchDispatcher::IdsVector>(
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
index 224e487..1d2edff4 100644
--- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
+++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
@@ -10,13 +10,11 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "components/gcm_driver/instance_id/instance_id.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
 #include "components/offline_pages/core/prefetch/prefetch_types.h"
 #include "components/offline_pages/task/task.h"
 
 namespace offline_pages {
-class PrefetchGCMHandler;
 class PrefetchNetworkRequestFactory;
 class PrefetchStore;
 
@@ -28,7 +26,6 @@
 
   GeneratePageBundleTask(PrefetchDispatcher* prefetch_dispatcher,
                          PrefetchStore* prefetch_store,
-                         PrefetchGCMHandler* gcm_handler,
                          const std::string& gcm_token,
                          PrefetchNetworkRequestFactory* request_factory,
                          PrefetchRequestFinishedCallback callback);
@@ -39,13 +36,9 @@
 
  private:
   void StartGeneratePageBundle(std::unique_ptr<UrlAndIds> url_and_ids);
-  void GotRegistrationId(std::unique_ptr<UrlAndIds> url_and_ids,
-                         const std::string& id,
-                         instance_id::InstanceID::Result result);
 
   PrefetchDispatcher* prefetch_dispatcher_;
   PrefetchStore* prefetch_store_;
-  PrefetchGCMHandler* gcm_handler_;
   std::string gcm_token_;
   PrefetchNetworkRequestFactory* request_factory_;
   PrefetchRequestFinishedCallback callback_;
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc
index 43546aa..5dc4496 100644
--- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc
+++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc
@@ -16,7 +16,6 @@
 #include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h"
 #include "components/offline_pages/core/prefetch/tasks/prefetch_task_test_base.h"
 #include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h"
-#include "components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h"
 #include "components/offline_pages/core/test_scoped_offline_clock.h"
 #include "components/offline_pages/task/task.h"
 #include "services/network/test/test_utils.h"
@@ -37,13 +36,11 @@
   GeneratePageBundleTaskTest() = default;
   ~GeneratePageBundleTaskTest() override = default;
 
-  TestPrefetchGCMHandler* gcm_handler() { return &gcm_handler_; }
   std::string gcm_token() { return "dummy_gcm_token"; }
 
   TestPrefetchDispatcher* dispatcher() { return &dispatcher_; }
 
  private:
-  TestPrefetchGCMHandler gcm_handler_;
   TestPrefetchDispatcher dispatcher_;
 };
 
@@ -52,16 +49,16 @@
 
   base::MockCallback<PrefetchRequestFinishedCallback> callback;
   RunTask(std::make_unique<GeneratePageBundleTask>(
-      dispatcher(), store(), gcm_handler(), gcm_token(),
-      prefetch_request_factory(), callback.Get()));
+      dispatcher(), store(), gcm_token(), prefetch_request_factory(),
+      callback.Get()));
   EXPECT_EQ(0, dispatcher()->generate_page_bundle_requested);
 }
 
 TEST_F(GeneratePageBundleTaskTest, EmptyTask) {
   base::MockCallback<PrefetchRequestFinishedCallback> callback;
   RunTask(std::make_unique<GeneratePageBundleTask>(
-      dispatcher(), store(), gcm_handler(), gcm_token(),
-      prefetch_request_factory(), callback.Get()));
+      dispatcher(), store(), gcm_token(), prefetch_request_factory(),
+      callback.Get()));
 
   EXPECT_FALSE(prefetch_request_factory()->HasOutstandingRequests());
   auto requested_urls = prefetch_request_factory()->GetAllUrlsRequested();
@@ -104,7 +101,7 @@
 
   clock.Advance(base::TimeDelta::FromHours(1));
 
-  GeneratePageBundleTask task(dispatcher(), store(), gcm_handler(), gcm_token(),
+  GeneratePageBundleTask task(dispatcher(), store(), gcm_token(),
                               prefetch_request_factory(),
                               request_callback.Get());
   RunTask(&task);
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index 1d20ae5..839db80 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -260,7 +260,7 @@
 
     deps = [
       "//base:base_java",
-      "//third_party/android_deps:android_support_compat_java",
+      "//third_party/android_deps:com_android_support_support_compat_java",
     ]
 
     srcjar_deps = [ ":browser_java_enums_srcjar" ]
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 801c474..4d42018 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -1341,7 +1341,13 @@
   }
   if (predictions.empty())
     return;
-  driver->AutofillDataReceived(predictions);
+
+  if (driver) {
+    // |driver_| is nullptr on iOS.
+    // TODO(https://crbug.com/831123): Remove propagating predictions to the
+    // renderer when the old parser is gone.
+    driver->AutofillDataReceived(predictions);
+  }
 }
 
 PasswordFormManager* PasswordManager::GetMatchingPendingManager(
diff --git a/components/safe_browsing/android/BUILD.gn b/components/safe_browsing/android/BUILD.gn
index d248e19..6d51566 100644
--- a/components/safe_browsing/android/BUILD.gn
+++ b/components/safe_browsing/android/BUILD.gn
@@ -8,7 +8,7 @@
 android_library("safe_browsing_java") {
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   java_files = [
     "java/src/org/chromium/components/safe_browsing/SafeBrowsingApiBridge.java",
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn
index 71bc6dee..4454a34 100644
--- a/components/signin/core/browser/android/BUILD.gn
+++ b/components/signin/core/browser/android/BUILD.gn
@@ -20,7 +20,7 @@
     "$google_play_services_package:google_play_services_basement_java",
     "//base:base_java",
     "//net/android:net_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
 
   java_files = [
@@ -55,7 +55,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/junit",
   ]
 }
@@ -67,7 +67,7 @@
     ":signin_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/jsr-305:jsr_305_javalib",
@@ -83,7 +83,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/jsr-305:jsr_305_javalib",
     "//third_party/junit",
   ]
diff --git a/components/signin/core/browser/signin_pref_names.cc b/components/signin/core/browser/signin_pref_names.cc
index c5923a5..75a77be 100644
--- a/components/signin/core/browser/signin_pref_names.cc
+++ b/components/signin/core/browser/signin_pref_names.cc
@@ -8,6 +8,10 @@
 
 #if defined(OS_CHROMEOS)
 // Boolean identifying if Mirror account consistency is required for profile.
+// If Chrome OS Account Manager is not available, this has the effect of
+// disabling secondary account sign-ins within the content area.
+// TODO(https://crbug.com/938835): Clean this up after releasing Chrome OS
+// Account Manager.
 const char kAccountConsistencyMirrorRequired[] =
     "account_consistency_mirror.required";
 #endif
diff --git a/components/sync/android/BUILD.gn b/components/sync/android/BUILD.gn
index 37b8fc2..f5dee92 100644
--- a/components/sync/android/BUILD.gn
+++ b/components/sync/android/BUILD.gn
@@ -10,7 +10,7 @@
     "//base:base_java",
     "//components/signin/core/browser/android:java",
     "//net/android:net_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_tools:android_gcm_java",
     "//third_party/cacheinvalidation:cacheinvalidation_javalib",
     "//third_party/cacheinvalidation:cacheinvalidation_proto_java",
diff --git a/components/ukm/debug/ukm_internals.js b/components/ukm/debug/ukm_internals.js
index 6aacd2da..7cffbd4d 100644
--- a/components/ukm/debug/ukm_internals.js
+++ b/components/ukm/debug/ukm_internals.js
@@ -408,13 +408,22 @@
       (!$('hide_no_metrics').checked || source.entries.length)
   ));
 
-  // Filter sources based on thread id.
+  // Filter sources based on thread id (High bits of UKM Recorder ID).
   const threadsFilteredSource = filteredSources.filter(source => {
+    // Get current selection for thread id. It is either -
+    // "All" for no restriction.
+    // "0" for the default thread. This is the thread that record f.e PageLoad
+    // <lowercase hex string for first 32 bit of source id> for other threads.
+    //     If a UKM is recorded with a custom source id or in renderer, it will
+    //     have a unique value for this shared by all metrics that use the
+    //     same thread.
     const selectedOption =
         $('thread_ids').options[$('thread_ids').selectedIndex];
-    return !selectedOption ||
-        (selectedOption.value === 'All') ||
-        ((source.id[0] >>> 0).toString() === selectedOption.value);
+    // Return true if either of the following is true -
+    // No option is selected or selected option is "All" or the hexadecimal
+    // representation of source id is matching.
+    return !selectedOption || (selectedOption.value === 'All') ||
+        ((source.id[0] >>> 0).toString(16) === selectedOption.value);
   });
 
   // Filter URLs based on URL selector input.
diff --git a/components/variations/android/BUILD.gn b/components/variations/android/BUILD.gn
index a1066de..95e4043 100644
--- a/components/variations/android/BUILD.gn
+++ b/components/variations/android/BUILD.gn
@@ -7,7 +7,7 @@
 android_library("variations_java") {
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_core_utils_java",
+    "//third_party/android_deps:com_android_support_support_core_utils_java",
   ]
   java_files = [
     "java/src/org/chromium/components/variations/VariationsAssociatedData.java",
diff --git a/components/viz/client/client_resource_provider.cc b/components/viz/client/client_resource_provider.cc
index efca8bb..2c59c0b 100644
--- a/components/viz/client/client_resource_provider.cc
+++ b/components/viz/client/client_resource_provider.cc
@@ -364,6 +364,7 @@
 
 ClientResourceProvider::ScopedSkSurface::ScopedSkSurface(
     GrContext* gr_context,
+    sk_sp<SkColorSpace> color_space,
     GLuint texture_id,
     GLenum texture_target,
     const gfx::Size& size,
@@ -381,7 +382,7 @@
   bool gpu_compositing = true;
   surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
       gr_context, backend_texture, kTopLeft_GrSurfaceOrigin, msaa_sample_count,
-      ResourceFormatToClosestSkColorType(gpu_compositing, format), nullptr,
+      ResourceFormatToClosestSkColorType(gpu_compositing, format), color_space,
       &surface_props);
 }
 
diff --git a/components/viz/client/client_resource_provider.h b/components/viz/client/client_resource_provider.h
index f3965af..b5d8c1d 100644
--- a/components/viz/client/client_resource_provider.h
+++ b/components/viz/client/client_resource_provider.h
@@ -113,6 +113,7 @@
   class VIZ_CLIENT_EXPORT ScopedSkSurface {
    public:
     ScopedSkSurface(GrContext* gr_context,
+                    sk_sp<SkColorSpace> color_space,
                     GLuint texture_id,
                     GLenum texture_target,
                     const gfx::Size& size,
diff --git a/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc b/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
index ae7a1c5..222748e 100644
--- a/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
+++ b/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
@@ -45,8 +45,8 @@
   pass->SetNew(render_pass_id, rect, rect, render_pass_transform);
 
   auto* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(shared_state_transform, rect, rect, rect, false, false,
-                       1, SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(shared_state_transform, rect, rect, gfx::RRectF(), rect,
+                       false, false, 1, SkBlendMode::kSrcOver, 0);
 
   auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
   surface_quad->SetNew(
@@ -173,7 +173,8 @@
   gfx::Rect rect4_root(kFrameRect);
   shared_quad_state4_root->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect4_root,
-      /*visible_quad_layer_rect=*/rect4_root, /*clip_rect=*/rect4_root,
+      /*visible_quad_layer_rect=*/rect4_root,
+      /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect4_root,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad4_root_1 =
@@ -336,7 +337,8 @@
   pass1->filters = filters;
   auto* shared_state_1 = pass1->CreateAndAppendSharedQuadState();
   shared_state_1->SetAll(invertible_transform, kFrameRect, kFrameRect,
-                         kFrameRect, false, false, 1, SkBlendMode::kSrcOver, 0);
+                         gfx::RRectF(), kFrameRect, false, false, 1,
+                         SkBlendMode::kSrcOver, 0);
 
   auto* surface_quad_1 = pass1->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
   surface_quad_1->SetNew(
@@ -384,7 +386,8 @@
   pass2->filters = filters2;
   auto* shared_state_2 = pass2->CreateAndAppendSharedQuadState();
   shared_state_2->SetAll(invertible_transform, kFrameRect, kFrameRect,
-                         kFrameRect, false, false, 1, SkBlendMode::kSrcOver, 0);
+                         gfx::RRectF(), kFrameRect, false, false, 1,
+                         SkBlendMode::kSrcOver, 0);
 
   auto* surface_quad_3 = pass2->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
   surface_quad_3->SetNew(
diff --git a/components/viz/common/quads/draw_quad_perftest.cc b/components/viz/common/quads/draw_quad_perftest.cc
index 6759fde2..99c0031 100644
--- a/components/viz/common/quads/draw_quad_perftest.cc
+++ b/components/viz/common/quads/draw_quad_perftest.cc
@@ -33,8 +33,8 @@
   SkBlendMode blend_mode = SkBlendMode::kSrcOver;
 
   SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
-  state->SetAll(quad_transform, content_rect, visible_layer_rect, clip_rect,
-                is_clipped, are_contents_opaque, opacity, blend_mode,
+  state->SetAll(quad_transform, content_rect, visible_layer_rect, gfx::RRectF(),
+                clip_rect, is_clipped, are_contents_opaque, opacity, blend_mode,
                 sorting_context_id);
   return state;
 }
diff --git a/components/viz/common/quads/draw_quad_unittest.cc b/components/viz/common/quads/draw_quad_unittest.cc
index 9992732..2eba2ba 100644
--- a/components/viz/common/quads/draw_quad_unittest.cc
+++ b/components/viz/common/quads/draw_quad_unittest.cc
@@ -48,8 +48,8 @@
   int sorting_context_id = 65536;
 
   auto state = std::make_unique<SharedQuadState>();
-  state->SetAll(quad_transform, layer_rect, visible_layer_rect, clip_rect,
-                is_clipped, are_contents_opaque, opacity, blend_mode,
+  state->SetAll(quad_transform, layer_rect, visible_layer_rect, gfx::RRectF(),
+                clip_rect, is_clipped, are_contents_opaque, opacity, blend_mode,
                 sorting_context_id);
 
   auto copy = std::make_unique<SharedQuadState>(*state);
@@ -74,8 +74,8 @@
   SkBlendMode blend_mode = SkBlendMode::kSrcOver;
 
   SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
-  state->SetAll(quad_transform, layer_rect, visible_layer_rect, clip_rect,
-                is_clipped, are_contents_opaque, opacity, blend_mode,
+  state->SetAll(quad_transform, layer_rect, visible_layer_rect, gfx::RRectF(),
+                clip_rect, is_clipped, are_contents_opaque, opacity, blend_mode,
                 sorting_context_id);
   return state;
 }
diff --git a/components/viz/common/quads/render_pass_unittest.cc b/components/viz/common/quads/render_pass_unittest.cc
index 9d106c7..d8b4729 100644
--- a/components/viz/common/quads/render_pass_unittest.cc
+++ b/components/viz/common/quads/render_pass_unittest.cc
@@ -98,8 +98,9 @@
 
   // Stick a quad in the pass, this should not get copied.
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), gfx::Rect(), gfx::Rect(), gfx::Rect(),
-                       false, false, 1, SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), gfx::Rect(), gfx::Rect(),
+                       gfx::RRectF(), gfx::Rect(), false, false, 1,
+                       SkBlendMode::kSrcOver, 0);
 
   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad->SetNew(pass->shared_quad_state_list.back(), gfx::Rect(),
@@ -155,7 +156,8 @@
   // Two quads using one shared state.
   SharedQuadState* shared_state1 = pass->CreateAndAppendSharedQuadState();
   shared_state1->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(),
-                        gfx::Rect(), false, false, 1, SkBlendMode::kSrcOver, 0);
+                        gfx::RRectF(), gfx::Rect(), false, false, 1,
+                        SkBlendMode::kSrcOver, 0);
 
   auto* color_quad1 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad1->SetNew(pass->shared_quad_state_list.back(),
@@ -170,7 +172,8 @@
   // And two quads using another shared state.
   SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
   shared_state2->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
-                        gfx::Rect(), false, false, 1, SkBlendMode::kSrcOver, 0);
+                        gfx::RRectF(), gfx::Rect(), false, false, 1,
+                        SkBlendMode::kSrcOver, 0);
 
   auto* color_quad3 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad3->SetNew(pass->shared_quad_state_list.back(),
@@ -211,8 +214,8 @@
   SharedQuadState* contrib_shared_state =
       contrib->CreateAndAppendSharedQuadState();
   contrib_shared_state->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2),
-                               gfx::Rect(), gfx::Rect(), false, false, 1,
-                               SkBlendMode::kSrcOver, 0);
+                               gfx::Rect(), gfx::RRectF(), gfx::Rect(), false,
+                               false, 1, SkBlendMode::kSrcOver, 0);
 
   auto* contrib_quad = contrib->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   contrib_quad->SetNew(contrib->shared_quad_state_list.back(),
@@ -264,7 +267,8 @@
   // A shared state with a quad.
   SharedQuadState* shared_state1 = pass->CreateAndAppendSharedQuadState();
   shared_state1->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(),
-                        gfx::Rect(), false, false, 1, SkBlendMode::kSrcOver, 0);
+                        gfx::RRectF(), gfx::Rect(), false, false, 1,
+                        SkBlendMode::kSrcOver, 0);
 
   auto* color_quad1 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad1->SetNew(pass->shared_quad_state_list.back(),
@@ -274,17 +278,20 @@
   // A shared state with no quads, they were culled.
   SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
   shared_state2->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
-                        gfx::Rect(), false, false, 1, SkBlendMode::kSrcOver, 0);
+                        gfx::RRectF(), gfx::Rect(), false, false, 1,
+                        SkBlendMode::kSrcOver, 0);
 
   // A second shared state with no quads.
   SharedQuadState* shared_state3 = pass->CreateAndAppendSharedQuadState();
   shared_state3->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
-                        gfx::Rect(), false, false, 1, SkBlendMode::kSrcOver, 0);
+                        gfx::RRectF(), gfx::Rect(), false, false, 1,
+                        SkBlendMode::kSrcOver, 0);
 
   // A last shared state with a quad again.
   SharedQuadState* shared_state4 = pass->CreateAndAppendSharedQuadState();
   shared_state4->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
-                        gfx::Rect(), false, false, 1, SkBlendMode::kSrcOver, 0);
+                        gfx::RRectF(), gfx::Rect(), false, false, 1,
+                        SkBlendMode::kSrcOver, 0);
 
   auto* color_quad2 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad2->SetNew(pass->shared_quad_state_list.back(),
diff --git a/components/viz/common/quads/shared_quad_state.cc b/components/viz/common/quads/shared_quad_state.cc
index 67e84ef..0c2c3bb 100644
--- a/components/viz/common/quads/shared_quad_state.cc
+++ b/components/viz/common/quads/shared_quad_state.cc
@@ -29,6 +29,7 @@
 void SharedQuadState::SetAll(const gfx::Transform& quad_to_target_transform,
                              const gfx::Rect& quad_layer_rect,
                              const gfx::Rect& visible_quad_layer_rect,
+                             const gfx::RRectF& rounded_corner_bounds,
                              const gfx::Rect& clip_rect,
                              bool is_clipped,
                              bool are_contents_opaque,
@@ -38,6 +39,7 @@
   this->quad_to_target_transform = quad_to_target_transform;
   this->quad_layer_rect = quad_layer_rect;
   this->visible_quad_layer_rect = visible_quad_layer_rect;
+  this->rounded_corner_bounds = rounded_corner_bounds;
   this->clip_rect = clip_rect;
   this->is_clipped = is_clipped;
   this->are_contents_opaque = are_contents_opaque;
@@ -51,6 +53,8 @@
   cc::MathUtil::AddToTracedValue("layer_content_rect", quad_layer_rect, value);
   cc::MathUtil::AddToTracedValue("layer_visible_content_rect",
                                  visible_quad_layer_rect, value);
+  cc::MathUtil::AddToTracedValue("rounded_corner_bounds", rounded_corner_bounds,
+                                 value);
 
   value->SetBoolean("is_clipped", is_clipped);
   cc::MathUtil::AddToTracedValue("clip_rect", clip_rect, value);
diff --git a/components/viz/common/quads/shared_quad_state.h b/components/viz/common/quads/shared_quad_state.h
index 1de514c1..d8dcf3c 100644
--- a/components/viz/common/quads/shared_quad_state.h
+++ b/components/viz/common/quads/shared_quad_state.h
@@ -10,6 +10,7 @@
 #include "components/viz/common/viz_common_export.h"
 #include "third_party/skia/include/core/SkBlendMode.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/rrect_f.h"
 #include "ui/gfx/transform.h"
 
 namespace base {
@@ -34,6 +35,7 @@
   void SetAll(const gfx::Transform& quad_to_target_transform,
               const gfx::Rect& layer_rect,
               const gfx::Rect& visible_layer_rect,
+              const gfx::RRectF& rounded_corner_bounds,
               const gfx::Rect& clip_rect,
               bool is_clipped,
               bool are_contents_opaque,
@@ -52,6 +54,9 @@
   // The size of the visible area in the quads' originating layer, in the space
   // of the quad rects.
   gfx::Rect visible_quad_layer_rect;
+  // This rect lives in the target content space. It defines the corner radius
+  // to clip the quads with.
+  gfx::RRectF rounded_corner_bounds;
   // This rect lives in the target content space.
   gfx::Rect clip_rect;
   bool is_clipped;
diff --git a/components/viz/demo/client/demo_client.cc b/components/viz/demo/client/demo_client.cc
index 7e45330b..a03e1f1c 100644
--- a/components/viz/demo/client/demo_client.cc
+++ b/components/viz/demo/client/demo_client.cc
@@ -105,6 +105,7 @@
         transform,
         /*quad_layer_rect=*/child_bounds,
         /*visible_quad_layer_rect=*/child_bounds,
+        /*rounded_corner_bounds=*/gfx::RRectF(),
         /*clip_rect=*/gfx::Rect(),
         /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
         /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
@@ -130,6 +131,7 @@
       gfx::Transform(),
       /*quad_layer_rect=*/output_rect,
       /*visible_quad_layer_rect=*/output_rect,
+      /*rounded_corner_bounds=*/gfx::RRectF(),
       /*clip_rect=*/gfx::Rect(),
       /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
       /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index af050b6..1fd04b6 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -289,6 +289,8 @@
       "display_embedder/gl_output_surface_android.h",
       "display_embedder/gl_output_surface_buffer_queue_android.cc",
       "display_embedder/gl_output_surface_buffer_queue_android.h",
+      "display_embedder/overlay_candidate_validator_android.cc",
+      "display_embedder/overlay_candidate_validator_android.h",
     ]
   }
 
@@ -445,7 +447,10 @@
   }
 
   if (is_android) {
-    sources += [ "frame_sinks/external_begin_frame_source_android_unittest.cc" ]
+    sources += [
+      "display_embedder/overlay_candidate_validator_android_unittest.cc",
+      "frame_sinks/external_begin_frame_source_android_unittest.cc",
+    ]
   }
 
   if (enable_vulkan) {
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto
index 7c29097..3134523 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto
@@ -23,6 +23,9 @@
   required Transform transform = 1;
   required Rect layer_rect = 2;
   required Rect visible_rect = 3;
+
+  // TODO(malaykeshav): add fuzzable rounded corner bounds.
+
   required Rect clip_rect = 4;
   required bool is_clipped = 5;
   required bool are_contents_opaque = 6;
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
index 988c4d4..aa695fb 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -124,7 +124,7 @@
     shared_quad_state->SetAll(
         GetTransformFromProtobuf(quad_spec.sqs().transform()),
         GetRectFromProtobuf(quad_spec.sqs().layer_rect()),
-        GetRectFromProtobuf(quad_spec.sqs().visible_rect()),
+        GetRectFromProtobuf(quad_spec.sqs().visible_rect()), gfx::RRectF(),
         GetRectFromProtobuf(quad_spec.sqs().clip_rect()),
         quad_spec.sqs().is_clipped(), quad_spec.sqs().are_contents_opaque(),
         Normalize(quad_spec.sqs().opacity()), SkBlendMode::kSrcOver,
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
index a3ed55ce..d6f9f15c 100644
--- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
+++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -113,6 +113,7 @@
   renderer_sqs->SetAll(gfx::Transform(1.0, 0.0, 0.0, 1.0, 0, 80),
                        gfx::Rect(kRendererFrameSize),
                        gfx::Rect(kRendererFrameSize),
+                       /*rounded_corner_bounds=*/gfx::RRectF(),
                        gfx::Rect(kRendererFrameSize), /*is_clipped=*/false,
                        /*are_contents_opaque=*/false, /*opacity=*/1,
                        SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
@@ -125,11 +126,12 @@
                        /*ignores_input_event=*/false);
 
   auto* toolbar_sqs = pass->CreateAndAppendSharedQuadState();
-  toolbar_sqs->SetAll(gfx::Transform(), gfx::Rect(kTopBarSize),
-                      gfx::Rect(kTopBarSize), gfx::Rect(kTopBarSize),
-                      /*is_clipped=*/false, /*are_contents_opaque=*/false,
-                      /*opacity=*/1, SkBlendMode::kSrcOver,
-                      /*sorting_context_id=*/0);
+  toolbar_sqs->SetAll(
+      gfx::Transform(), gfx::Rect(kTopBarSize), gfx::Rect(kTopBarSize),
+      /*rounded_corner_bounds=*/gfx::RRectF(), gfx::Rect(kTopBarSize),
+      /*is_clipped=*/false, /*are_contents_opaque=*/false,
+      /*opacity=*/1, SkBlendMode::kSrcOver,
+      /*sorting_context_id=*/0);
   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad->SetNew(toolbar_sqs, gfx::Rect(kTopBarSize),
                      gfx::Rect(kTopBarSize), SK_ColorLTGRAY,
diff --git a/components/viz/service/display/display_perftest.cc b/components/viz/service/display/display_perftest.cc
index d6f91b7..e0b4e2e0 100644
--- a/components/viz/service/display/display_perftest.cc
+++ b/components/viz/service/display/display_perftest.cc
@@ -66,7 +66,8 @@
     SkBlendMode blend_mode = SkBlendMode::kSrcOver;
 
     SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
-    state->SetAll(quad_transform, rect, rect, rect, is_clipped,
+    state->SetAll(quad_transform, rect, rect,
+                  /*rounded_corner_bounds=*/gfx::RRectF(), rect, is_clipped,
                   are_contents_opaque, opacity, blend_mode, sorting_context_id);
     return state;
   }
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc
index 926fe2c..0ec87b65 100644
--- a/components/viz/service/display/display_unittest.cc
+++ b/components/viz/service/display/display_unittest.cc
@@ -791,8 +791,8 @@
   // |    |
   // +----+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -816,12 +816,12 @@
   // +----+ |
   //   +----+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -851,12 +851,12 @@
   //   |  |                                    |  |
   //   +--+                                    +--+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -885,12 +885,12 @@
   // +----+                                      +----+
   //  +--+                                        +--+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect7, rect7, rect7, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect7, rect7, gfx::RRectF(),
+                              rect7, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(gfx::Transform(), rect6, rect6, rect6,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect6, rect6, gfx::RRectF(),
+                               rect6, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect7, rect7, SK_ColorBLACK, false);
@@ -918,12 +918,12 @@
   // |    |   +--+
   // +----+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(gfx::Transform(), rect4, rect4, rect4,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect4, rect4, gfx::RRectF(),
+                               rect4, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -950,12 +950,12 @@
   // +-----+|
   // +------+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(gfx::Transform(), rect5, rect5, rect5,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect5, rect5, gfx::RRectF(),
+                               rect5, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1013,11 +1013,11 @@
   //                         |     |
   //                         +-----+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                               rect1, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1038,11 +1038,11 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1064,11 +1064,11 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1090,12 +1090,12 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(gfx::Transform(), rect4, rect4, rect4,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect4, rect4, gfx::RRectF(),
+                               rect4, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1156,13 +1156,13 @@
   // |        |               |        |
   // +--------+               +--------+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), more_then_minimum_size,
-                               more_then_minimum_size, more_then_minimum_size,
-                               is_clipped, are_contents_opaque, opacity,
-                               SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(
+        gfx::Transform(), more_then_minimum_size, more_then_minimum_size,
+        gfx::RRectF(), more_then_minimum_size, is_clipped, are_contents_opaque,
+        opacity, SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, more_then_minimum_size,
                   more_then_minimum_size, SK_ColorBLACK, false);
@@ -1180,12 +1180,13 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
     shared_quad_state2->SetAll(gfx::Transform(), minimum_size, minimum_size,
-                               minimum_size, is_clipped, are_contents_opaque,
-                               opacity, SkBlendMode::kSrcOver, 0);
+                               gfx::RRectF(), minimum_size, is_clipped,
+                               are_contents_opaque, opacity,
+                               SkBlendMode::kSrcOver, 0);
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1208,13 +1209,13 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), less_than_minimum_size,
-                               less_than_minimum_size, less_than_minimum_size,
-                               is_clipped, are_contents_opaque, opacity,
-                               SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(
+        gfx::Transform(), less_than_minimum_size, less_than_minimum_size,
+        gfx::RRectF(), less_than_minimum_size, is_clipped, are_contents_opaque,
+        opacity, SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, less_than_minimum_size,
                   less_than_minimum_size, SK_ColorBLACK, false);
@@ -1267,14 +1268,14 @@
   auto* quad3 = frame.render_pass_list.front()
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
 
-  shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                            are_contents_opaque, opacity, SkBlendMode::kSrcOver,
-                            0);
-  shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2, is_clipped,
-                             are_contents_opaque, opacity,
+  shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                            rect1, is_clipped, are_contents_opaque, opacity,
+                            SkBlendMode::kSrcOver, 0);
+  shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                             rect2, is_clipped, are_contents_opaque, opacity,
                              SkBlendMode::kSrcOver, 0);
-  shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3, is_clipped,
-                             are_contents_opaque, opacity,
+  shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                             rect3, is_clipped, are_contents_opaque, opacity,
                              SkBlendMode::kSrcOver, 0);
   quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
   quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -1343,11 +1344,11 @@
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(half_scale, rect2, rect2, rect2, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(half_scale, rect2, rect2, gfx::RRectF(), rect2,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1366,11 +1367,11 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(half_scale, rect3, rect3, rect3, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(half_scale, rect3, rect3, gfx::RRectF(), rect3,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1389,12 +1390,12 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(half_scale, rect4, rect4, rect4, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(half_scale, rect4, rect4, gfx::RRectF(), rect4,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1412,8 +1413,8 @@
   }
 
   {
-    shared_quad_state->SetAll(double_scale, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(double_scale, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1430,12 +1431,12 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(double_scale, rect5, rect5, rect5, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(double_scale, rect5, rect5, gfx::RRectF(), rect5,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1458,12 +1459,12 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(double_scale, rect6, rect6, rect6, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(double_scale, rect6, rect6, gfx::RRectF(), rect6,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1487,12 +1488,12 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(double_scale, rect7, rect7, rect7, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(double_scale, rect7, rect7, gfx::RRectF(), rect7,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1515,12 +1516,12 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(double_scale, rect8, rect8, rect8, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(double_scale, rect8, rect8, gfx::RRectF(), rect8,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1543,12 +1544,12 @@
   }
 
   {
-    shared_quad_state->SetAll(double_scale, rect10, rect10, rect10, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(double_scale, rect10, rect10, gfx::RRectF(),
+                              rect10, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
-    shared_quad_state2->SetAll(double_scale, rect9, rect9, rect9, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(double_scale, rect9, rect9, gfx::RRectF(), rect9,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect10, rect10, SK_ColorBLACK, false);
@@ -1604,11 +1605,11 @@
   gfx::Transform inverted;
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(zero_scale, rect, rect, rect, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(zero_scale, rect, rect, gfx::RRectF(), rect,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1628,11 +1629,11 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(epsilon_scale, rect, rect, rect, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(epsilon_scale, rect, rect, gfx::RRectF(), rect,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 1);
 
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1658,11 +1659,11 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(larger_epsilon_scale, rect, rect, rect,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(larger_epsilon_scale, rect, rect, gfx::RRectF(),
+                               rect, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1709,11 +1710,11 @@
 
   {
     negative_scale.Scale3d(-1, 1, 1);
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(negative_scale, rect, rect, rect, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(negative_scale, rect, rect, gfx::RRectF(), rect,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1741,11 +1742,11 @@
   {
     negative_scale.MakeIdentity();
     negative_scale.Scale3d(1, -1, 1);
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(negative_scale, rect, rect, rect, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(negative_scale, rect, rect, gfx::RRectF(), rect,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1773,11 +1774,11 @@
   {
     negative_scale.MakeIdentity();
     negative_scale.Scale3d(1, 1, -1);
-    shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(negative_scale, rect, rect, rect, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(negative_scale, rect, rect, gfx::RRectF(), rect,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1838,11 +1839,11 @@
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
   {
     // Apply rotation transform on |rect1| only.
-    shared_quad_state->SetAll(rotate, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(rotate, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -1862,11 +1863,11 @@
 
   {
     // Apply rotation transform on |rect1| and |rect2|.
-    shared_quad_state->SetAll(rotate, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(rotate, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(rotate, rect2, rect2, rect2, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(rotate, rect2, rect2, gfx::RRectF(), rect2,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -1884,11 +1885,11 @@
   {
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(rotate, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(rotate, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -1910,11 +1911,11 @@
     // Since we only support updating |visible_rect| of DrawQuad with scale
     // or translation transform and rotation transform applies to quads,
     // |visible_rect| of |quad2| should not be changed.
-    shared_quad_state->SetAll(rotate, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(rotate, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(rotate, rect3, rect3, rect3, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(rotate, rect3, rect3, gfx::RRectF(), rect3,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -1965,11 +1966,11 @@
   auto* quad2 = frame.render_pass_list.front()
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
   {
-    shared_quad_state->SetAll(perspective, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(perspective, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                               rect1, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect1, rect1, SK_ColorBLACK, false);
@@ -1989,11 +1990,11 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(perspective, rect2, rect2, rect2, is_clipped,
-                               are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(perspective, rect2, rect2, gfx::RRectF(), rect2,
+                               is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2037,11 +2038,11 @@
   auto* quad2 = frame.render_pass_list.front()
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacityLess1,
-                              SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, are_contents_opaque, opacity1,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque,
+                              opacityLess1, SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, are_contents_opaque, opacity1,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2059,11 +2060,11 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity1,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity1,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, are_contents_opaque, opacity1,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, are_contents_opaque, opacity1,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2104,11 +2105,11 @@
   auto* quad2 = frame.render_pass_list.front()
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              transparent_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, transparent_content, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2126,11 +2127,11 @@
   }
 
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2178,11 +2179,11 @@
   //                         |     |
   //                         +-----+
   {
-    shared_quad_state->SetAll(translate_back, rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(translate_back, rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 1);
-    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                               is_clipped, are_contents_opaque, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                               rect1, is_clipped, are_contents_opaque, opacity,
                                SkBlendMode::kSrcOver, 1);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -2238,11 +2239,11 @@
     //   +----+
     //           +-+
     //           +-+
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              transparent_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, transparent_content, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2267,11 +2268,11 @@
     //   +----+                       =>                              | +-+ |
     //           +-+                                                  | +-+ |
     //           +-+                                                  +-----+
-    shared_quad_state->SetAll(translate_up, rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(translate_up, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2297,11 +2298,11 @@
     //           +---+                                                 +----+
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(translate_up, rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(translate_up, rect1, rect1, gfx::RRectF(), rect1,
+                              is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -2363,14 +2364,14 @@
     //   |    |----+             =>        |    |----+
     //   +----+                            +----+
     //
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2398,8 +2399,8 @@
     //
     quad3 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state3->SetAll(gfx::Transform(), rect4, rect4, rect4,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect4, rect4, gfx::RRectF(),
+                               rect4, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad3->SetNew(shared_quad_state3, rect4, rect4, SK_ColorBLACK, false);
     EXPECT_EQ(3u, frame.render_pass_list.front()->quad_list.size());
@@ -2427,8 +2428,8 @@
     //   |    |----+           =>          | |  |--|-+
     //   +----+                            +-|--+  |
     //                                       +-----+
-    shared_quad_state3->SetAll(gfx::Transform(), rect5, rect5, rect5,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect5, rect5, gfx::RRectF(),
+                               rect5, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad3->SetNew(shared_quad_state3, rect5, rect5, SK_ColorBLACK, false);
     EXPECT_EQ(3u, frame.render_pass_list.front()->quad_list.size());
@@ -2494,14 +2495,14 @@
     //   |    |----+             =>        |    |----+
     //   +----+                            +----+
     //
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2566,11 +2567,11 @@
     //   +----+
     //
 
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                               rect1, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad1->SetNew(shared_quad_state2, rect1, rect1, render_pass_id,
@@ -2630,11 +2631,11 @@
     //   |   | ||
     //   +------+
     //
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                              non_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, non_clipped, opaque_content, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               non_clipped, opaque_content, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, non_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2657,11 +2658,11 @@
     //
     quad2 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, clip_rect,
-                              clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              clip_rect, clipped, opaque_content, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               non_clipped, opaque_content, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, non_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2686,11 +2687,11 @@
     //   |   +-+|             =>                      +--+++
     //   +------+
     //
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, clip_rect,
-                              clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              clip_rect, clipped, opaque_content, opacity,
                               SkBlendMode::kSrcOver, 0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               non_clipped, opaque_content, opacity,
+    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, non_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -2737,11 +2738,11 @@
   auto* quad2 = frame.render_pass_list.front()
                     ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2807,17 +2808,17 @@
     // |       |   |        |
     // |   R1  |   |    R2  |
     // +-------+---+--------+
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                               rect2, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state4->SetAll(gfx::Transform(), rect4, rect4, rect4,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state4->SetAll(gfx::Transform(), rect4, rect4, gfx::RRectF(),
+                               rect4, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     R1->SetNew(shared_quad_state, rect1, rect1, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
@@ -2855,17 +2856,17 @@
     // |       |           |
     // |   R2  |       R1  |
     // +-------+-----------+
-    shared_quad_state->SetAll(gfx::Transform(), rect5, rect5, rect5, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect5, rect5, gfx::RRectF(),
+                              rect5, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                               rect1, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state4->SetAll(gfx::Transform(), rect6, rect6, rect6,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state4->SetAll(gfx::Transform(), rect6, rect6, gfx::RRectF(),
+                               rect6, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     R1->SetNew(shared_quad_state, rect5, rect5, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
@@ -2902,17 +2903,17 @@
     // |-----+     |       |
     // |   R2      |   R1  |
     // +-----------+-------+
-    shared_quad_state->SetAll(gfx::Transform(), rect5, rect5, rect5, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect5, rect5, gfx::RRectF(),
+                              rect5, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                               rect1, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
-    shared_quad_state4->SetAll(gfx::Transform(), rect7, rect7, rect7,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state4->SetAll(gfx::Transform(), rect7, rect7, gfx::RRectF(),
+                               rect7, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     R1->SetNew(shared_quad_state, rect5, rect5, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
@@ -2993,12 +2994,13 @@
     // +--+--+
     // |  |  |
     // +--+--+
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
     shared_quad_state2->SetAll(gfx::Transform(), rect_in_rect1, rect_in_rect1,
-                               rect_in_rect1, is_clipped, opaque_content,
-                               opacity, SkBlendMode::kSrcOver, 0);
+                               gfx::RRectF(), rect_in_rect1, is_clipped,
+                               opaque_content, opacity, SkBlendMode::kSrcOver,
+                               0);
     quad1->SetNew(shared_quad_state, rect1_1, rect1_1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state, rect1_2, rect1_2, SK_ColorBLACK, false);
     quad3->SetNew(shared_quad_state, rect1_3, rect1_3, SK_ColorBLACK, false);
@@ -3034,10 +3036,10 @@
     // +--+--+
     quad5 = frame.render_pass_list.front()
                 ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state2->SetAll(gfx::Transform(), rect_intersects_rect1,
-                               rect_intersects_rect1, rect_intersects_rect1,
-                               is_clipped, opaque_content, opacity,
-                               SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(
+        gfx::Transform(), rect_intersects_rect1, rect_intersects_rect1,
+        gfx::RRectF(), rect_intersects_rect1, is_clipped, opaque_content,
+        opacity, SkBlendMode::kSrcOver, 0);
     quad5->SetNew(shared_quad_state2, rect_intersects_rect1,
                   rect_intersects_rect1, SK_ColorBLACK, false);
     EXPECT_EQ(5u, frame.render_pass_list.front()->quad_list.size());
@@ -3075,11 +3077,11 @@
 
     auto* quad6 = frame.render_pass_list.front()
                       ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
-    shared_quad_state->SetAll(gfx::Transform(), rect2, rect2, rect2, is_clipped,
-                              opaque_content, opacity, SkBlendMode::kSrcOver,
-                              0);
-    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, rect3,
-                               is_clipped, opaque_content, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect2, rect2, gfx::RRectF(),
+                              rect2, is_clipped, opaque_content, opacity,
+                              SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(gfx::Transform(), rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
     quad1->SetNew(shared_quad_state, rect2_1, rect2_1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state, rect2_2, rect2_2, SK_ColorBLACK, false);
@@ -3167,15 +3169,15 @@
     // |quad1| forms an occlusion rect; |quad2| follows a invertible transform
     // and is hiding behind quad1; |quad3| follows a non-invertible transform
     // and it is not covered by the occlusion rect.
-    shared_quad_state1->SetAll(invertible, rect1, rect1, rect1, is_clipped,
-                               opaque_content, opacity, SkBlendMode::kSrcOver,
-                               0);
-    shared_quad_state2->SetAll(invertible, rect2, rect2, rect2, is_clipped,
-                               opaque_content, opacity, SkBlendMode::kSrcOver,
-                               0);
-    shared_quad_state3->SetAll(non_invertible, rect3, rect3, rect3, is_clipped,
-                               opaque_content, opacity, SkBlendMode::kSrcOver,
-                               0);
+    shared_quad_state1->SetAll(invertible, rect1, rect1, gfx::RRectF(), rect1,
+                               is_clipped, opaque_content, opacity,
+                               SkBlendMode::kSrcOver, 0);
+    shared_quad_state2->SetAll(invertible, rect2, rect2, gfx::RRectF(), rect2,
+                               is_clipped, opaque_content, opacity,
+                               SkBlendMode::kSrcOver, 0);
+    shared_quad_state3->SetAll(non_invertible, rect3, rect3, gfx::RRectF(),
+                               rect3, is_clipped, opaque_content, opacity,
+                               SkBlendMode::kSrcOver, 0);
     quad1->SetNew(shared_quad_state1, rect1, rect1, SK_ColorBLACK, false);
     quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
     quad3->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
@@ -3201,12 +3203,12 @@
     // +--------+                 +--------+
     // Verify if draw occlusion can occlude quad with non-invertible
     // transfrom.
-    shared_quad_state1->SetAll(invertible, rect1, rect1, rect1, is_clipped,
-                               opaque_content, opacity, SkBlendMode::kSrcOver,
-                               0);
-    shared_quad_state3->SetAll(non_invertible_miss_z, rect3, rect3, rect3,
+    shared_quad_state1->SetAll(invertible, rect1, rect1, gfx::RRectF(), rect1,
                                is_clipped, opaque_content, opacity,
                                SkBlendMode::kSrcOver, 0);
+    shared_quad_state3->SetAll(non_invertible_miss_z, rect3, rect3,
+                               gfx::RRectF(), rect3, is_clipped, opaque_content,
+                               opacity, SkBlendMode::kSrcOver, 0);
     quad1->SetNew(shared_quad_state1, rect1, rect1, SK_ColorBLACK, false);
     quad3->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
 
@@ -3246,8 +3248,8 @@
   // |    |
   // +----+
   {
-    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
-                              are_contents_opaque, opacity,
+    shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, gfx::RRectF(),
+                              rect1, is_clipped, are_contents_opaque, opacity,
                               SkBlendMode::kSrcOver, 0);
 
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -3314,7 +3316,8 @@
     gfx::Rect rect1(display_size);
     shared_quad_state1->SetAll(
         gfx::Transform(), rect1 /* quad_layer_rect */,
-        rect1 /* visible_quad_layer_rect */, rect1 /*clip_rect */,
+        rect1 /* visible_quad_layer_rect */,
+        gfx::RRectF() /* rounded_corner_bounds*/, rect1 /*clip_rect */,
         false /* is_clipped */, false /* are_contents_opaque */,
         0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
     auto* quad1 = pass->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -3326,7 +3329,8 @@
     gfx::Rect rect2(gfx::Point(20, 20), sub_surface_size);
     shared_quad_state2->SetAll(
         gfx::Transform(), rect2 /* quad_layer_rect */,
-        rect2 /* visible_quad_layer_rect */, rect2 /*clip_rect */,
+        rect2 /* visible_quad_layer_rect */,
+        gfx::RRectF() /* rounded_corner_bounds */, rect2 /*clip_rect */,
         false /* is_clipped */, true /* are_contents_opaque */,
         1.0f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
     auto* quad2 = pass->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index 0a6b9d8..584ac05 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -693,8 +693,9 @@
       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
-                       gfx::Rect(1023, 1023), gfx::Rect(1023, 1023), false,
-                       false, 1, SkBlendMode::kSrcOver, 0);
+                       gfx::Rect(1023, 1023), gfx::RRectF(),
+                       gfx::Rect(1023, 1023), false, false, 1,
+                       SkBlendMode::kSrcOver, 0);
   overlay_quad->SetNew(shared_state, gfx::Rect(1023, 1023),
                        gfx::Rect(1023, 1023), needs_blending, resource_id,
                        premultiplied_alpha, uv_top_left, uv_bottom_right,
@@ -755,8 +756,9 @@
       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
-                       gfx::Rect(1025, 1025), gfx::Rect(1025, 1025), false,
-                       false, 1, SkBlendMode::kSrcOver, 0);
+                       gfx::Rect(1025, 1025), gfx::RRectF(),
+                       gfx::Rect(1025, 1025), false, false, 1,
+                       SkBlendMode::kSrcOver, 0);
   overlay_quad->SetNew(shared_state, gfx::Rect(1025, 1025),
                        gfx::Rect(1025, 1025), needs_blending, resource_id,
                        premultiplied_alpha, uv_top_left, uv_bottom_right,
@@ -2473,8 +2475,9 @@
       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
-                       gfx::Rect(viewport_size), gfx::Rect(viewport_size),
-                       false, false, 1, SkBlendMode::kSrcOver, 0);
+                       gfx::Rect(viewport_size), gfx::RRectF(),
+                       gfx::Rect(viewport_size), false, false, 1,
+                       SkBlendMode::kSrcOver, 0);
   overlay_quad->SetNew(shared_state, gfx::Rect(viewport_size),
                        gfx::Rect(viewport_size), needs_blending,
                        parent_resource_id, premultiplied_alpha, uv_top_left,
@@ -2856,8 +2859,8 @@
       gfx::RectF tex_coord_rect(0, 0, 1, 1);
       SharedQuadState* shared_state =
           root_pass->CreateAndAppendSharedQuadState();
-      shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, false, 1,
-                           SkBlendMode::kSrcOver, 0);
+      shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
+                           false, false, 1, SkBlendMode::kSrcOver, 0);
       YUVVideoDrawQuad* quad =
           root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
       quad->SetNew(shared_state, rect, rect, needs_blending, tex_coord_rect,
@@ -4140,8 +4143,9 @@
       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
-                       gfx::Rect(50, 50), gfx::Rect(viewport_size), false,
-                       false, 1, SkBlendMode::kSrcOver, 0);
+                       gfx::Rect(50, 50), gfx::RRectF(),
+                       gfx::Rect(viewport_size), false, false, 1,
+                       SkBlendMode::kSrcOver, 0);
   overlay_quad->SetNew(
       shared_state, gfx::Rect(viewport_size), gfx::Rect(viewport_size),
       needs_blending, create_overlay_resource(), premultiplied_alpha,
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 22feb9f..2cd3ef1 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -144,8 +144,9 @@
   int sorting_context_id = 0;
   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
-                       clip_rect, is_clipped, are_contents_opaque, opacity,
-                       blend_mode, sorting_context_id);
+                       /*rounded_corner_bounds=*/gfx::RRectF(), clip_rect,
+                       is_clipped, are_contents_opaque, opacity, blend_mode,
+                       sorting_context_id);
   return shared_state;
 }
 
@@ -163,8 +164,9 @@
   int sorting_context_id = 0;
   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
   shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
-                       clip_rect, is_clipped, are_contents_opaque, opacity,
-                       blend_mode, sorting_context_id);
+                       /*rounded_corner_bounds=*/gfx::RRectF(), clip_rect,
+                       is_clipped, are_contents_opaque, opacity, blend_mode,
+                       sorting_context_id);
   return shared_state;
 }
 
diff --git a/components/viz/service/display/software_renderer_unittest.cc b/components/viz/service/display/software_renderer_unittest.cc
index 4aff55f..853ef75 100644
--- a/components/viz/service/display/software_renderer_unittest.cc
+++ b/components/viz/service/display/software_renderer_unittest.cc
@@ -147,8 +147,8 @@
   SharedQuadState* shared_quad_state =
       root_render_pass->CreateAndAppendSharedQuadState();
   shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
-                            outer_rect, false, true, 1.0, SkBlendMode::kSrcOver,
-                            0);
+                            gfx::RRectF(), outer_rect, false, true, 1.0,
+                            SkBlendMode::kSrcOver, 0);
   auto* inner_quad =
       root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, SK_ColorCYAN,
@@ -215,8 +215,8 @@
   SharedQuadState* shared_quad_state =
       root_render_pass->CreateAndAppendSharedQuadState();
   shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
-                            outer_rect, false, true, 1.0, SkBlendMode::kSrcOver,
-                            0);
+                            gfx::RRectF(), outer_rect, false, true, 1.0,
+                            SkBlendMode::kSrcOver, 0);
   auto* inner_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, needs_blending,
                      mapped_resource_cyan, gfx::RectF(gfx::SizeF(inner_size)),
@@ -275,8 +275,9 @@
                            gfx::Transform());
   SharedQuadState* shared_quad_state =
       root_render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(gfx::Transform(), tile_rect, tile_rect, tile_rect,
-                            false, true, 1.0, SkBlendMode::kSrcOver, 0);
+  shared_quad_state->SetAll(gfx::Transform(), tile_rect, tile_rect,
+                            gfx::RRectF(), tile_rect, false, true, 1.0,
+                            SkBlendMode::kSrcOver, 0);
   auto* quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   quad->SetNew(shared_quad_state, tile_rect, tile_rect, needs_blending,
                mapped_resource_cyan, gfx::RectF(gfx::SizeF(tile_size)),
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index c08fab0..9aa6b7d 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -542,6 +542,7 @@
       /*quad_to_target_transform=*/gfx::Transform(),
       /*quad_layer_rect=*/output_rect,
       /*visible_quad_layer_rect=*/output_rect,
+      /*rounded_corner_bounds=*/gfx::RRectF(),
       /*clip_rect=*/gfx::Rect(),
       /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
       /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
@@ -593,9 +594,10 @@
 
   shared_quad_state->SetAll(
       new_transform, quad_layer_rect, visible_quad_layer_rect,
-      new_clip_rect.rect, new_clip_rect.is_clipped,
-      source_sqs->are_contents_opaque, source_sqs->opacity,
-      source_sqs->blend_mode, source_sqs->sorting_context_id);
+      source_sqs->rounded_corner_bounds, new_clip_rect.rect,
+      new_clip_rect.is_clipped, source_sqs->are_contents_opaque,
+      source_sqs->opacity, source_sqs->blend_mode,
+      source_sqs->sorting_context_id);
   shared_quad_state->has_surface_damage = has_surface_damage;
 
   return shared_quad_state;
diff --git a/components/viz/service/display/surface_aggregator_pixeltest.cc b/components/viz/service/display/surface_aggregator_pixeltest.cc
index 3422dd0..1021e7a1 100644
--- a/components/viz/service/display/surface_aggregator_pixeltest.cc
+++ b/components/viz/service/display/surface_aggregator_pixeltest.cc
@@ -67,14 +67,16 @@
     const gfx::Size& size) {
   const gfx::Rect layer_rect = gfx::Rect(size);
   const gfx::Rect visible_layer_rect = gfx::Rect(size);
+  const gfx::RRectF rounded_corner_bounds = gfx::RRectF();
   const gfx::Rect clip_rect = gfx::Rect(size);
   bool is_clipped = false;
   bool are_contents_opaque = false;
   float opacity = 1.f;
   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
   auto* shared_state = render_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(transform, layer_rect, visible_layer_rect, clip_rect,
-                       is_clipped, are_contents_opaque, opacity, blend_mode, 0);
+  shared_state->SetAll(transform, layer_rect, visible_layer_rect,
+                       rounded_corner_bounds, clip_rect, is_clipped,
+                       are_contents_opaque, opacity, blend_mode, 0);
   return shared_state;
 }
 
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 0aa827e..83bd96e2 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -316,6 +316,7 @@
     gfx::Transform layer_to_target_transform = transform;
     gfx::Rect layer_bounds(primary_surface_rect);
     gfx::Rect visible_layer_rect(primary_surface_rect);
+    gfx::RRectF rounded_corner_bounds = gfx::RRectF();
     gfx::Rect clip_rect(primary_surface_rect);
     bool is_clipped = false;
     bool are_contents_opaque = false;
@@ -323,8 +324,9 @@
 
     auto* shared_quad_state = pass->CreateAndAppendSharedQuadState();
     shared_quad_state->SetAll(layer_to_target_transform, layer_bounds,
-                              visible_layer_rect, clip_rect, is_clipped,
-                              are_contents_opaque, opacity, blend_mode, 0);
+                              visible_layer_rect, rounded_corner_bounds,
+                              clip_rect, is_clipped, are_contents_opaque,
+                              opacity, blend_mode, 0);
 
     SurfaceDrawQuad* surface_quad =
         pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
@@ -338,8 +340,8 @@
     gfx::Rect output_rect = gfx::Rect(0, 0, 5, 5);
     auto* shared_state = pass->CreateAndAppendSharedQuadState();
     shared_state->SetAll(gfx::Transform(), output_rect, output_rect,
-                         output_rect, false, false, 1, SkBlendMode::kSrcOver,
-                         0);
+                         gfx::RRectF(), output_rect, false, false, 1,
+                         SkBlendMode::kSrcOver, 0);
     auto* quad = pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
     quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, 0,
                  gfx::RectF(), gfx::Size(), gfx::Vector2dF(), gfx::PointF(),
@@ -2144,6 +2146,7 @@
   const gfx::Transform layer_to_target_transform;
   const gfx::Rect layer_rect(size);
   const gfx::Rect visible_layer_rect(size);
+  const gfx::RRectF rounded_corner_bounds = gfx::RRectF();
   const gfx::Rect clip_rect(size);
 
   bool is_clipped = false;
@@ -2154,8 +2157,8 @@
   bool force_anti_aliasing_off = false;
   auto* sqs = pass->CreateAndAppendSharedQuadState();
   sqs->SetAll(layer_to_target_transform, layer_rect, visible_layer_rect,
-              clip_rect, is_clipped, are_contents_opaque, opacity, blend_mode,
-              0);
+              rounded_corner_bounds, clip_rect, is_clipped, are_contents_opaque,
+              opacity, blend_mode, 0);
 
   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad->SetNew(pass->shared_quad_state_list.back(), visible_layer_rect,
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc b/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc
index 8797564..391f9265 100644
--- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc
+++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc
@@ -4,56 +4,9 @@
 
 #include "components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.h"
 
-#include "components/viz/service/display/overlay_strategy_fullscreen.h"
-#include "components/viz/service/display/overlay_strategy_single_on_top.h"
-#include "components/viz/service/display/overlay_strategy_underlay.h"
-#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h"
 #include "third_party/khronos/GLES2/gl2.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gl/android/android_surface_control_compat.h"
 
 namespace viz {
-namespace {
-class OverlayCandidateValidatorImpl : public OverlayCandidateValidator {
- public:
-  OverlayCandidateValidatorImpl() = default;
-  ~OverlayCandidateValidatorImpl() override = default;
-
-  void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
-    // Added in priority order, most to least desirable.
-    strategies->push_back(std::make_unique<OverlayStrategyFullscreen>(this));
-    strategies->push_back(std::make_unique<OverlayStrategySingleOnTop>(this));
-    strategies->push_back(std::make_unique<OverlayStrategyUnderlay>(
-        this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates));
-  }
-  bool AllowCALayerOverlays() override { return false; }
-  bool AllowDCLayerOverlays() override { return false; }
-  void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
-    DCHECK(!surfaces->empty());
-
-    // Only update the last candidate that was added to the list. All previous
-    // overlays should have already been handled.
-    auto& candidate = surfaces->back();
-    if (!gl::SurfaceControl::SupportsColorSpace(candidate.color_space)) {
-      DCHECK(!candidate.use_output_surface_for_resource)
-          << "The main overlay must only use color space supported by the "
-             "device";
-      candidate.overlay_handled = false;
-      return;
-    }
-
-    candidate.display_rect =
-        gfx::RectF(gfx::ToEnclosingRect(candidate.display_rect));
-    candidate.overlay_handled = true;
-
-#if DCHECK_IS_ON()
-    for (auto& candidate : *surfaces)
-      DCHECK(candidate.overlay_handled);
-#endif
-  }
-};
-
-}  // namespace
 
 GLOutputSurfaceBufferQueueAndroid::GLOutputSurfaceBufferQueueAndroid(
     scoped_refptr<VizProcessContextProvider> context_provider,
@@ -66,16 +19,16 @@
                                  synthetic_begin_frame_source,
                                  gpu_memory_buffer_manager,
                                  GL_TEXTURE_2D,
-                                 buffer_format),
-      overlay_candidate_validator_(
-          std::make_unique<OverlayCandidateValidatorImpl>()) {}
+                                 buffer_format) {}
 
 GLOutputSurfaceBufferQueueAndroid::~GLOutputSurfaceBufferQueueAndroid() =
     default;
 
 OverlayCandidateValidator*
 GLOutputSurfaceBufferQueueAndroid::GetOverlayCandidateValidator() const {
-  return overlay_candidate_validator_.get();
+  // TODO(khushalsagar): The API shouldn't be const.
+  return &const_cast<GLOutputSurfaceBufferQueueAndroid*>(this)
+              ->overlay_candidate_validator_;
 }
 
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.h b/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.h
index 134006f..bf8f72c 100644
--- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.h
+++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.h
@@ -6,6 +6,8 @@
 #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_BUFFER_QUEUE_ANDROID_H_
 
 #include "components/viz/service/display_embedder/gl_output_surface_buffer_queue.h"
+
+#include "components/viz/service/display_embedder/overlay_candidate_validator_android.h"
 #include "ui/gfx/buffer_types.h"
 
 namespace viz {
@@ -24,7 +26,7 @@
   OverlayCandidateValidator* GetOverlayCandidateValidator() const override;
 
  private:
-  std::unique_ptr<OverlayCandidateValidator> overlay_candidate_validator_;
+  OverlayCandidateValidatorAndroid overlay_candidate_validator_;
 
   DISALLOW_COPY_AND_ASSIGN(GLOutputSurfaceBufferQueueAndroid);
 };
diff --git a/components/viz/service/display_embedder/overlay_candidate_validator_android.cc b/components/viz/service/display_embedder/overlay_candidate_validator_android.cc
new file mode 100644
index 0000000..78b1392
--- /dev/null
+++ b/components/viz/service/display_embedder/overlay_candidate_validator_android.cc
@@ -0,0 +1,93 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/display_embedder/overlay_candidate_validator_android.h"
+
+#include "cc/base/math_util.h"
+#include "components/viz/service/display/overlay_strategy_fullscreen.h"
+#include "components/viz/service/display/overlay_strategy_single_on_top.h"
+#include "components/viz/service/display/overlay_strategy_underlay.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gl/android/android_surface_control_compat.h"
+
+namespace viz {
+namespace {
+
+gfx::RectF ClipFromOrigin(gfx::RectF input) {
+  if (input.x() < 0.f) {
+    input.set_width(input.width() + input.x());
+    input.set_x(0.f);
+  }
+
+  if (input.y() < 0) {
+    input.set_height(input.height() + input.y());
+    input.set_y(0.f);
+  }
+
+  return input;
+}
+
+}  // namespace
+
+OverlayCandidateValidatorAndroid::OverlayCandidateValidatorAndroid() = default;
+OverlayCandidateValidatorAndroid::~OverlayCandidateValidatorAndroid() = default;
+
+void OverlayCandidateValidatorAndroid::GetStrategies(
+    OverlayProcessor::StrategyList* strategies) {
+  // Added in priority order, most to least desirable.
+  strategies->push_back(std::make_unique<OverlayStrategyFullscreen>(this));
+  strategies->push_back(std::make_unique<OverlayStrategySingleOnTop>(this));
+  strategies->push_back(std::make_unique<OverlayStrategyUnderlay>(
+      this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates));
+}
+
+bool OverlayCandidateValidatorAndroid::AllowCALayerOverlays() {
+  return false;
+}
+
+bool OverlayCandidateValidatorAndroid::AllowDCLayerOverlays() {
+  return false;
+}
+
+void OverlayCandidateValidatorAndroid::CheckOverlaySupport(
+    OverlayCandidateList* surfaces) {
+  DCHECK(!surfaces->empty());
+
+  // Only update the last candidate that was added to the list. All previous
+  // overlays should have already been handled.
+  auto& candidate = surfaces->back();
+  if (!gl::SurfaceControl::SupportsColorSpace(candidate.color_space)) {
+    DCHECK(!candidate.use_output_surface_for_resource)
+        << "The main overlay must only use color space supported by the "
+           "device";
+    candidate.overlay_handled = false;
+    return;
+  }
+
+  const gfx::RectF orig_display_rect =
+      gfx::RectF(gfx::ToEnclosingRect(candidate.display_rect));
+
+  candidate.display_rect = orig_display_rect;
+  if (candidate.is_clipped)
+    candidate.display_rect.Intersect(gfx::RectF(candidate.clip_rect));
+
+  // The framework doesn't support display rects positioned at a negative
+  // offset.
+  candidate.display_rect = ClipFromOrigin(candidate.display_rect);
+  if (candidate.display_rect.IsEmpty()) {
+    candidate.overlay_handled = false;
+    return;
+  }
+
+  candidate.uv_rect = cc::MathUtil::ScaleRectProportional(
+      candidate.uv_rect, orig_display_rect, candidate.display_rect);
+  candidate.overlay_handled = true;
+
+#if DCHECK_IS_ON()
+  for (auto& candidate : *surfaces)
+    DCHECK(candidate.overlay_handled);
+#endif
+}
+
+}  // namespace viz
diff --git a/components/viz/service/display_embedder/overlay_candidate_validator_android.h b/components/viz/service/display_embedder/overlay_candidate_validator_android.h
new file mode 100644
index 0000000..ee498faba
--- /dev/null
+++ b/components/viz/service/display_embedder/overlay_candidate_validator_android.h
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_OVERLAY_CANDIDATE_VALIDATOR_ANDROID_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_OVERLAY_CANDIDATE_VALIDATOR_ANDROID_H_
+
+#include "components/viz/service/display/overlay_candidate_validator.h"
+#include "components/viz/service/viz_service_export.h"
+
+namespace viz {
+
+class VIZ_SERVICE_EXPORT OverlayCandidateValidatorAndroid
+    : public OverlayCandidateValidator {
+ public:
+  OverlayCandidateValidatorAndroid();
+  ~OverlayCandidateValidatorAndroid() override;
+
+  void GetStrategies(OverlayProcessor::StrategyList* strategies) override;
+  bool AllowCALayerOverlays() override;
+  bool AllowDCLayerOverlays() override;
+  void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OverlayCandidateValidatorAndroid);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_OVERLAY_CANDIDATE_VALIDATOR_ANDROID_H_
diff --git a/components/viz/service/display_embedder/overlay_candidate_validator_android_unittest.cc b/components/viz/service/display_embedder/overlay_candidate_validator_android_unittest.cc
new file mode 100644
index 0000000..6ba5a5ec
--- /dev/null
+++ b/components/viz/service/display_embedder/overlay_candidate_validator_android_unittest.cc
@@ -0,0 +1,87 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/display_embedder/overlay_candidate_validator_android.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/test/gfx_util.h"
+
+namespace viz {
+
+TEST(OverlayCandidateValidatorAndroidTest, NoClipOrNegativeOffset) {
+  OverlayCandidate candidate;
+  candidate.display_rect = gfx::RectF(10.f, 10.f);
+  candidate.uv_rect = gfx::RectF(1.f, 1.f);
+  candidate.is_clipped = false;
+  candidate.clip_rect = gfx::Rect(5, 5);
+  candidate.overlay_handled = false;
+
+  OverlayCandidateList candidates;
+  candidates.push_back(candidate);
+
+  OverlayCandidateValidatorAndroid validator;
+  validator.CheckOverlaySupport(&candidates);
+  EXPECT_TRUE(candidates.at(0).overlay_handled);
+  EXPECT_RECTF_EQ(candidates.at(0).display_rect, gfx::RectF(10.f, 10.f));
+}
+
+TEST(OverlayCandidateValidatorAndroidTest, Clipped) {
+  OverlayCandidate candidate;
+  candidate.display_rect = gfx::RectF(10.f, 10.f);
+  candidate.uv_rect = gfx::RectF(1.f, 1.f);
+  candidate.is_clipped = true;
+  candidate.clip_rect = gfx::Rect(2, 2, 5, 5);
+  candidate.overlay_handled = false;
+
+  OverlayCandidateList candidates;
+  candidates.push_back(candidate);
+
+  OverlayCandidateValidatorAndroid validator;
+  validator.CheckOverlaySupport(&candidates);
+  EXPECT_TRUE(candidates.at(0).overlay_handled);
+  EXPECT_RECTF_EQ(candidates.at(0).display_rect,
+                  gfx::RectF(2.f, 2.f, 5.f, 5.f));
+  EXPECT_RECTF_EQ(candidates.at(0).uv_rect, gfx::RectF(0.2f, 0.2f, 0.5f, 0.5f));
+}
+
+TEST(OverlayCandidateValidatorAndroidTest, NegativeOffset) {
+  OverlayCandidate candidate;
+  candidate.display_rect = gfx::RectF(-2.f, -4.f, 10.f, 10.f);
+  candidate.uv_rect = gfx::RectF(0.5f, 0.5f);
+  candidate.is_clipped = false;
+  candidate.clip_rect = gfx::Rect(5, 5);
+  candidate.overlay_handled = false;
+
+  OverlayCandidateList candidates;
+  candidates.push_back(candidate);
+
+  OverlayCandidateValidatorAndroid validator;
+  validator.CheckOverlaySupport(&candidates);
+  EXPECT_TRUE(candidates.at(0).overlay_handled);
+  EXPECT_RECTF_EQ(candidates.at(0).display_rect,
+                  gfx::RectF(0.f, 0.f, 8.f, 6.f));
+  EXPECT_RECTF_EQ(candidates.at(0).uv_rect, gfx::RectF(0.1f, 0.2f, 0.4f, 0.3f));
+}
+
+TEST(OverlayCandidateValidatorAndroidTest, ClipAndNegativeOffset) {
+  OverlayCandidate candidate;
+  candidate.display_rect = gfx::RectF(-5.0f, -5.0f, 10.0f, 10.0f);
+  candidate.uv_rect = gfx::RectF(0.5f, 0.5f, 0.5f, 0.5f);
+  candidate.is_clipped = true;
+  candidate.clip_rect = gfx::Rect(5, 5);
+  candidate.overlay_handled = false;
+
+  OverlayCandidateList candidates;
+  candidates.push_back(candidate);
+
+  OverlayCandidateValidatorAndroid validator;
+  validator.CheckOverlaySupport(&candidates);
+  EXPECT_TRUE(candidates.at(0).overlay_handled);
+  EXPECT_RECTF_EQ(candidates.at(0).display_rect,
+                  gfx::RectF(0.f, 0.f, 5.f, 5.f));
+  EXPECT_RECTF_EQ(candidates.at(0).uv_rect,
+                  gfx::RectF(0.75f, 0.75f, 0.25f, 0.25f));
+}
+
+}  // namespace viz
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 5e1af789..0fb8ca1c 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
@@ -579,7 +579,10 @@
 
   // |context_provider_| and clients want either the context to be lost or made
   // current on destruction.
-  MakeCurrent(false /* need_fbo0 */);
+  if (MakeCurrent(false /* need_fbo0 */)) {
+    // This ensures any outstanding callbacks for promise images are performed.
+    gr_context()->flush();
+  }
   copier_ = nullptr;
   texture_deleter_ = nullptr;
   context_provider_ = nullptr;
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index 1ef6ae0..1b70c10 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -174,7 +174,8 @@
   gfx::Rect rect1(display_rect_);
   shared_quad_state1->SetAll(
       gfx::Transform(), rect1 /* quad_layer_rect */,
-      rect1 /* visible_quad_layer_rect */, rect1 /*clip_rect */,
+      rect1 /* visible_quad_layer_rect */,
+      gfx::RRectF() /* rounded_corner_bounds */, rect1 /*clip_rect */,
       false /* is_clipped */, false /* are_contents_opaque */,
       0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
   auto* quad1 = pass1->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -210,7 +211,8 @@
   transform2.Translate(-200, -100);
   shared_quad_state2->SetAll(
       transform2, rect2 /* quad_layer_rect */,
-      rect2 /* visible_quad_layer_rect */, rect2 /*clip_rect */,
+      rect2 /* visible_quad_layer_rect */,
+      gfx::RRectF() /* rounded_corner_bounds */, rect2 /*clip_rect */,
       false /* is_clipped */, false /* are_contents_opaque */,
       0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
   auto* quad2 = pass2->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
@@ -227,7 +229,8 @@
   gfx::Rect rect3(display_rect_);
   shared_quad_state3->SetAll(
       gfx::Transform(), rect3 /* quad_layer_rect */,
-      rect3 /* visible_quad_layer_rect */, rect3 /*clip_rect */,
+      rect3 /* visible_quad_layer_rect */,
+      gfx::RRectF() /* rounded_corner_bounds */, rect3 /*clip_rect */,
       false /* is_clipped */, false /* are_contents_opaque */,
       0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
   auto* quad3 = pass3->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -250,7 +253,8 @@
   transform4.matrix().set(3, 3, 0.f);
   shared_quad_state4->SetAll(
       transform4, rect4 /* quad_layer_rect */,
-      rect4 /* visible_quad_layer_rect */, rect4 /*clip_rect */,
+      rect4 /* visible_quad_layer_rect */,
+      gfx::RRectF() /* rounded_corner_bounds */, rect4 /*clip_rect */,
       false /* is_clipped */, false /* are_contents_opaque */,
       0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
   auto* quad4 = pass4->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
@@ -267,7 +271,8 @@
   gfx::Rect rect5_root(display_rect_);
   shared_quad_state5_root->SetAll(
       gfx::Transform(), /*quad_layer_rect=*/rect5_root,
-      /*visible_quad_layer_rect=*/rect5_root, /*clip_rect=*/rect5_root,
+      /*visible_quad_layer_rect=*/rect5_root,
+      gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect5_root,
       /*is_clipped=*/false, /*are_contents_opaque=*/false,
       /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
   auto* quad5_root_1 =
@@ -332,7 +337,8 @@
     gfx::Rect rect1(display_rect_);
     shared_quad_state1->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect1,
-        /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1,
+        /*visible_quad_layer_rect=*/rect1,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect1,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad1 = pass1->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -352,7 +358,8 @@
     gfx::Rect rect2(display_rect_);
     shared_quad_state2->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect2,
-        /*visible_quad_layer_rect=*/rect2, /*clip_rect=*/rect2,
+        /*visible_quad_layer_rect=*/rect2,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect2,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad2 = pass2->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -384,7 +391,8 @@
     transform3_0.Translate(-200, -100);
     shared_quad_state3_0->SetAll(
         transform3_0, /*quad_layer_rect=*/rect3_0,
-        /*visible_quad_layer_rect=*/rect3_0, /*clip_rect=*/rect3_0,
+        /*visible_quad_layer_rect=*/rect3_0,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect3_0,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad3_0 = pass3_0->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
@@ -403,7 +411,8 @@
     gfx::Rect rect3_1(display_rect_);
     shared_quad_state3_1->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect3_1,
-        /*visible_quad_layer_rect=*/rect3_1, /*clip_rect=*/rect3_1,
+        /*visible_quad_layer_rect=*/rect3_1,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect3_1,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad3_1 =
@@ -421,7 +430,8 @@
     gfx::Rect rect3_root(display_rect_);
     shared_quad_state3_root->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect3_root,
-        /*visible_quad_layer_rect=*/rect3_root, /*clip_rect=*/rect3_root,
+        /*visible_quad_layer_rect=*/rect3_root,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect3_root,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad3_root_1 =
@@ -456,7 +466,8 @@
     transform4_0.Translate(-199, -100);
     shared_quad_state4_0->SetAll(
         transform4_0, /*quad_layer_rect=*/rect4_0,
-        /*visible_quad_layer_rect=*/rect4_0, /*clip_rect=*/rect4_0,
+        /*visible_quad_layer_rect=*/rect4_0,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect4_0,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad4_0 = pass4_0->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
@@ -475,7 +486,8 @@
     gfx::Rect rect4_1(display_rect_);
     shared_quad_state4_1->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect4_1,
-        /*visible_quad_layer_rect=*/rect4_1, /*clip_rect=*/rect4_1,
+        /*visible_quad_layer_rect=*/rect4_1,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect4_1,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad4_1 =
@@ -493,7 +505,8 @@
     gfx::Rect rect4_root(display_rect_);
     shared_quad_state4_root->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect4_root,
-        /*visible_quad_layer_rect=*/rect4_root, /*clip_rect=*/rect4_root,
+        /*visible_quad_layer_rect=*/rect4_root,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect4_root,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad4_root_1 =
@@ -530,7 +543,8 @@
     transform5_0.Translate(-199, -100);
     shared_quad_state5_0->SetAll(
         transform5_0, /*quad_layer_rect=*/rect5_0,
-        /*visible_quad_layer_rect=*/rect5_0, /*clip_rect=*/rect5_0,
+        /*visible_quad_layer_rect=*/rect5_0,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect5_0,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad5_0 = pass5_0->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
@@ -549,7 +563,8 @@
     gfx::Rect rect5_1(display_rect_);
     shared_quad_state5_1->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect5_1,
-        /*visible_quad_layer_rect=*/rect5_1, /*clip_rect=*/rect5_1,
+        /*visible_quad_layer_rect=*/rect5_1,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect5_1,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad5_1 =
@@ -567,7 +582,8 @@
     gfx::Rect rect5_root(display_rect_);
     shared_quad_state5_root->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect5_root,
-        /*visible_quad_layer_rect=*/rect5_root, /*clip_rect=*/rect5_root,
+        /*visible_quad_layer_rect=*/rect5_root,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect5_root,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad5_root_1 =
@@ -605,7 +621,8 @@
     transform6_0.Translate(-199, -100);
     shared_quad_state6_0->SetAll(
         transform6_0, /*quad_layer_rect=*/rect6_0,
-        /*visible_quad_layer_rect=*/rect6_0, /*clip_rect=*/rect6_0,
+        /*visible_quad_layer_rect=*/rect6_0,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect6_0,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad6_0 = pass6_0->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
@@ -624,7 +641,8 @@
     gfx::Rect rect6_1(display_rect_);
     shared_quad_state6_1->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect6_1,
-        /*visible_quad_layer_rect=*/rect6_1, /*clip_rect=*/rect6_1,
+        /*visible_quad_layer_rect=*/rect6_1,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect6_1,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad6_1 =
@@ -642,7 +660,8 @@
     gfx::Rect rect6_root(display_rect_);
     shared_quad_state6_root->SetAll(
         gfx::Transform(), /*quad_layer_rect=*/rect6_root,
-        /*visible_quad_layer_rect=*/rect6_root, /*clip_rect=*/rect6_root,
+        /*visible_quad_layer_rect=*/rect6_root,
+        gfx::RRectF() /* rounded_corner_bounds */, /*clip_rect=*/rect6_root,
         /*is_clipped=*/false, /*are_contents_opaque=*/false,
         /*opacity=*/0.6f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
     auto* quad6_root_1 =
diff --git a/components/viz/test/surface_hittest_test_helpers.cc b/components/viz/test/surface_hittest_test_helpers.cc
index 0d19edf..4e3ec60 100644
--- a/components/viz/test/surface_hittest_test_helpers.cc
+++ b/components/viz/test/surface_hittest_test_helpers.cc
@@ -18,8 +18,9 @@
                            const gfx::Transform& transform,
                            const gfx::Rect& root_rect) {
   SharedQuadState* child_shared_state = pass->CreateAndAppendSharedQuadState();
-  child_shared_state->SetAll(transform, root_rect, root_rect, root_rect, false,
-                             false, 1.0f, SkBlendMode::kSrcOver, 0);
+  child_shared_state->SetAll(transform, root_rect, root_rect, gfx::RRectF(),
+                             root_rect, false, false, 1.0f,
+                             SkBlendMode::kSrcOver, 0);
 }
 
 void CreateSolidColorDrawQuad(RenderPass* pass,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index e7f5b90a..3d6d1cd 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -186,6 +186,7 @@
     "//third_party/boringssl",
     "//third_party/brotli:dec",
     "//third_party/icu",
+    "//third_party/inspector_protocol:encoding",
     "//third_party/libyuv",
     "//third_party/re2",
     "//third_party/sqlite",
@@ -477,6 +478,8 @@
     "background_fetch/storage/start_next_pending_request_task.h",
     "background_sync/background_sync_context_impl.cc",
     "background_sync/background_sync_context_impl.h",
+    "background_sync/background_sync_launcher.cc",
+    "background_sync/background_sync_launcher.h",
     "background_sync/background_sync_manager.cc",
     "background_sync/background_sync_manager.h",
     "background_sync/background_sync_metrics.cc",
@@ -660,6 +663,8 @@
     "devtools/devtools_renderer_channel.h",
     "devtools/devtools_session.cc",
     "devtools/devtools_session.h",
+    "devtools/devtools_session_encoding.cc",
+    "devtools/devtools_session_encoding.h",
     "devtools/devtools_stream_blob.cc",
     "devtools/devtools_stream_blob.h",
     "devtools/devtools_stream_file.cc",
@@ -1651,8 +1656,6 @@
     "service_worker/service_worker_context_core.cc",
     "service_worker/service_worker_context_core.h",
     "service_worker/service_worker_context_core_observer.h",
-    "service_worker/service_worker_context_request_handler.cc",
-    "service_worker/service_worker_context_request_handler.h",
     "service_worker/service_worker_context_watcher.cc",
     "service_worker/service_worker_context_watcher.h",
     "service_worker/service_worker_context_wrapper.cc",
diff --git a/content/browser/background_sync/background_sync.proto b/content/browser/background_sync/background_sync.proto
index c65aed9..b1ba296 100644
--- a/content/browser/background_sync/background_sync.proto
+++ b/content/browser/background_sync/background_sync.proto
@@ -14,6 +14,10 @@
   NETWORK_STATE_ONLINE = 2;
 }
 
+message PeriodicSyncOptions {
+  optional int64 min_interval = 1;
+}
+
 message BackgroundSyncRegistrationProto {
   // required int64 id = 1;
   required string tag = 2;
@@ -23,6 +27,7 @@
   // required SyncPowerState power_state = 6;
   required int32 num_attempts = 7;
   required int64 delay_until = 8;
+  optional PeriodicSyncOptions periodic_sync_options = 9;
 }
 
 message BackgroundSyncRegistrationsProto {
diff --git a/content/browser/background_sync/background_sync_context_impl.cc b/content/browser/background_sync/background_sync_context_impl.cc
index e2e9b9ce..231111d 100644
--- a/content/browser/background_sync/background_sync_context_impl.cc
+++ b/content/browser/background_sync/background_sync_context_impl.cc
@@ -9,6 +9,8 @@
 #include "base/bind.h"
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
+#include "build/build_config.h"
+#include "content/browser/background_sync/background_sync_launcher.h"
 #include "content/browser/background_sync/background_sync_manager.h"
 #include "content/browser/background_sync/background_sync_service_impl.h"
 #include "content/browser/devtools/devtools_background_services_context.h"
@@ -80,10 +82,32 @@
   background_sync_manager_ = std::move(manager);
 }
 
-void BackgroundSyncContextImpl::FireBackgroundSyncEventsForStoragePartition(
-    content::StoragePartition* storage_partition,
+void BackgroundSyncContextImpl::set_wakeup_delta_for_testing(
+    base::TimeDelta wakeup_delta) {
+  test_wakeup_delta_ = wakeup_delta;
+}
+
+base::TimeDelta BackgroundSyncContextImpl::GetSoonestWakeupDelta() {
+  if (!test_wakeup_delta_.is_max())
+    return test_wakeup_delta_;
+
+  if (!background_sync_manager_)
+    return base::TimeDelta::Max();
+
+  return background_sync_manager_->GetSoonestWakeupDelta();
+}
+
+void BackgroundSyncContextImpl::GetSoonestWakeupDeltaAcrossPartitions(
+    BrowserContext* browser_context,
+    base::OnceCallback<void(base::TimeDelta)> callback) {
+  DCHECK(browser_context);
+
+  BackgroundSyncLauncher::GetSoonestWakeupDelta(browser_context,
+                                                std::move(callback));
+}
+
+void BackgroundSyncContextImpl::FireBackgroundSyncEvents(
     base::OnceClosure done_closure) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!background_sync_manager_) {
     std::move(done_closure).Run();
     return;
@@ -92,6 +116,15 @@
       std::move(done_closure));
 }
 
+#if defined(OS_ANDROID)
+void BackgroundSyncContextImpl::FireBackgroundSyncEventsAcrossPartitions(
+    BrowserContext* browser_context,
+    const base::android::JavaParamRef<jobject>& j_runnable) {
+  DCHECK(browser_context);
+  BackgroundSyncLauncher::FireBackgroundSyncEvents(browser_context, j_runnable);
+}
+#endif
+
 void BackgroundSyncContextImpl::CreateBackgroundSyncManager(
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
     scoped_refptr<DevToolsBackgroundServicesContext> devtools_context) {
diff --git a/content/browser/background_sync/background_sync_context_impl.h b/content/browser/background_sync/background_sync_context_impl.h
index 9365f80b..68c33276 100644
--- a/content/browser/background_sync/background_sync_context_impl.h
+++ b/content/browser/background_sync/background_sync_context_impl.h
@@ -11,6 +11,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/background_sync_context.h"
 #include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h"
@@ -54,9 +56,16 @@
   BackgroundSyncManager* background_sync_manager() const;
 
   // BackgroundSyncContext implementation.
-  void FireBackgroundSyncEventsForStoragePartition(
-      content::StoragePartition* storage_partition,
-      base::OnceClosure done_closure) override;
+  void FireBackgroundSyncEvents(base::OnceClosure done_closure) override;
+#if defined(OS_ANDROID)
+  void FireBackgroundSyncEventsAcrossPartitions(
+      BrowserContext* browser_context,
+      const base::android::JavaParamRef<jobject>& j_runnable) override;
+#endif
+  base::TimeDelta GetSoonestWakeupDelta() override;
+  void GetSoonestWakeupDeltaAcrossPartitions(
+      BrowserContext* browser_context,
+      base::OnceCallback<void(base::TimeDelta)> callback) override;
 
  protected:
   friend class base::RefCountedDeleteOnSequence<BackgroundSyncContextImpl>;
@@ -65,9 +74,11 @@
 
   void set_background_sync_manager_for_testing(
       std::unique_ptr<BackgroundSyncManager> manager);
+  void set_wakeup_delta_for_testing(base::TimeDelta wakeup_delta);
 
  private:
   friend class BackgroundSyncServiceImplTest;
+  friend class BackgroundSyncLauncherTest;
 
   virtual void CreateBackgroundSyncManager(
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
@@ -87,6 +98,7 @@
   std::map<BackgroundSyncServiceImpl*,
            std::unique_ptr<BackgroundSyncServiceImpl>>
       services_;
+  base::TimeDelta test_wakeup_delta_ = base::TimeDelta::Max();
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundSyncContextImpl);
 };
diff --git a/content/browser/background_sync/background_sync_launcher.cc b/content/browser/background_sync/background_sync_launcher.cc
new file mode 100644
index 0000000..efab1e5
--- /dev/null
+++ b/content/browser/background_sync/background_sync_launcher.cc
@@ -0,0 +1,120 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_sync/background_sync_launcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "content/public/browser/background_sync_context.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#if defined(OS_ANDROID)
+#include "base/android/callback_android.h"
+#include "base/barrier_closure.h"
+#endif
+
+namespace content {
+
+namespace {
+
+base::LazyInstance<BackgroundSyncLauncher>::DestructorAtExit
+    g_background_sync_launcher = LAZY_INSTANCE_INITIALIZER;
+
+#if defined(OS_ANDROID)
+unsigned int GetStoragePartitionCount(BrowserContext* browser_context) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(browser_context);
+
+  int num_partitions = 0;
+  BrowserContext::ForEachStoragePartition(
+      browser_context,
+      base::BindRepeating(
+          [](int* num_partitions, StoragePartition* storage_partition) {
+            (*num_partitions)++;
+          },
+          &num_partitions));
+
+  // It's valid for a profile to not have any storage partitions. This DCHECK
+  // is to ensure that we're not waking up Chrome for no reason, because that's
+  // expensive and unnecessary.
+  DCHECK(num_partitions);
+
+  return num_partitions;
+}
+#endif
+
+}  // namespace
+
+// static
+BackgroundSyncLauncher* BackgroundSyncLauncher::Get() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  return g_background_sync_launcher.Pointer();
+}
+
+// static
+void BackgroundSyncLauncher::GetSoonestWakeupDelta(
+    BrowserContext* browser_context,
+    base::OnceCallback<void(base::TimeDelta)> callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
+  BrowserContext::ForEachStoragePartition(
+      browser_context, base::BindRepeating(
+                           [](base::TimeDelta* soonest_wakeup_delta,
+                              StoragePartition* storage_partition) {
+                             BackgroundSyncContext* sync_context =
+                                 storage_partition->GetBackgroundSyncContext();
+                             DCHECK(sync_context);
+
+                             base::TimeDelta wakeup_delta =
+                                 sync_context->GetSoonestWakeupDelta();
+                             if (wakeup_delta < *soonest_wakeup_delta)
+                               *soonest_wakeup_delta = wakeup_delta;
+                           },
+                           &soonest_wakeup_delta));
+  std::move(callback).Run(soonest_wakeup_delta);
+}
+
+// static
+#if defined(OS_ANDROID)
+void BackgroundSyncLauncher::FireBackgroundSyncEvents(
+    BrowserContext* browser_context,
+    const base::android::JavaParamRef<jobject>& j_runnable) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(browser_context);
+
+  base::RepeatingClosure done_closure = base::BarrierClosure(
+      GetStoragePartitionCount(browser_context),
+      base::BindOnce(base::android::RunRunnableAndroid,
+                     base::android::ScopedJavaGlobalRef<jobject>(j_runnable)));
+
+  BrowserContext::ForEachStoragePartition(
+      browser_context,
+      base::BindRepeating(
+          [](base::RepeatingClosure done_closure,
+             StoragePartition* storage_partition) {
+            BackgroundSyncContext* sync_context =
+                storage_partition->GetBackgroundSyncContext();
+            DCHECK(sync_context);
+            sync_context->FireBackgroundSyncEvents(std::move(done_closure));
+          },
+          std::move(done_closure)));
+}
+#endif
+
+BackgroundSyncLauncher::BackgroundSyncLauncher() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+BackgroundSyncLauncher::~BackgroundSyncLauncher() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/background_sync/background_sync_launcher.h b/content/browser/background_sync/background_sync_launcher.h
new file mode 100644
index 0000000..28d6acba
--- /dev/null
+++ b/content/browser/background_sync/background_sync_launcher.h
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_LAUNCHER_H_
+#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_LAUNCHER_H_
+
+#include "base/callback_forward.h"
+#include "base/lazy_instance.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#endif
+
+namespace content {
+
+class BrowserContext;
+
+class CONTENT_EXPORT BackgroundSyncLauncher {
+ public:
+  static BackgroundSyncLauncher* Get();
+  static void GetSoonestWakeupDelta(
+      BrowserContext* browser_context,
+      base::OnceCallback<void(base::TimeDelta)> callback);
+#if defined(OS_ANDROID)
+  static void FireBackgroundSyncEvents(
+      BrowserContext* browser_context,
+      const base::android::JavaParamRef<jobject>& j_runnable);
+#endif
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<BackgroundSyncLauncher>;
+  friend class BackgroundSyncLauncherTest;
+
+  // Constructor and destructor marked private to enforce singleton.
+  BackgroundSyncLauncher();
+  ~BackgroundSyncLauncher();
+
+  base::TimeDelta soonest_wakeup_delta_ = base::TimeDelta::Max();
+  DISALLOW_COPY_AND_ASSIGN(BackgroundSyncLauncher);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_LAUNCHER_H_
\ No newline at end of file
diff --git a/content/browser/background_sync/background_sync_launcher_unittest.cc b/content/browser/background_sync/background_sync_launcher_unittest.cc
new file mode 100644
index 0000000..6a81ee3
--- /dev/null
+++ b/content/browser/background_sync/background_sync_launcher_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_sync/background_sync_launcher.h"
+
+#include <map>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/time/time.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/background_sync_context.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+const char kUrl_1[] = "https://example.com";
+const char kUrl_2[] = "https://whereswaldo.com";
+
+class TestBrowserClient : public ContentBrowserClient {
+ public:
+  TestBrowserClient() = default;
+  ~TestBrowserClient() override = default;
+
+  void GetStoragePartitionConfigForSite(BrowserContext* browser_context,
+                                        const GURL& site,
+                                        bool can_be_default,
+                                        std::string* partition_domain,
+                                        std::string* partition_name,
+                                        bool* in_memory) override {
+    DCHECK(browser_context);
+    DCHECK(partition_domain);
+    DCHECK(partition_name);
+
+    auto partition_num = std::to_string(++partition_count_);
+    *partition_domain = std::string("PartitionDomain") + partition_num;
+    *partition_name = std::string("Partition") + partition_num;
+    *in_memory = false;
+  }
+
+ private:
+  int partition_count_ = 0;
+};
+
+}  // namespace
+
+class BackgroundSyncLauncherTest : public testing::Test {
+ public:
+  BackgroundSyncLauncherTest()
+      : browser_thread_bundle_(TestBrowserThreadBundle::MainThreadType::UI) {}
+
+  void SetUpBrowserContext(const std::vector<GURL>& urls,
+                           const std::map<GURL, int>& wakeup_deltas = {}) {
+    DCHECK(!urls.empty());
+
+    for (const auto& url : urls) {
+      auto* storage_partition = BrowserContext::GetStoragePartitionForSite(
+          &test_browser_context_, url);
+
+      auto iter = wakeup_deltas.find(url);
+      if (iter == wakeup_deltas.end())
+        continue;
+
+      static_cast<StoragePartitionImpl*>(storage_partition)
+          ->GetBackgroundSyncContext()
+          ->set_wakeup_delta_for_testing(
+              base::TimeDelta::FromMilliseconds(iter->second));
+    }
+  }
+
+  void SetUp() override {
+    original_client_ = SetBrowserClientForTesting(&browser_client_);
+  }
+
+  void TearDown() override { SetBrowserClientForTesting(original_client_); }
+
+  base::TimeDelta GetSoonestWakeupDelta() {
+    base::TimeDelta to_return;
+    BackgroundSyncLauncher::GetSoonestWakeupDelta(
+        &test_browser_context_, base::BindOnce(
+                                    [](base::TimeDelta* to_return,
+                                       base::TimeDelta soonest_wakeup_delta) {
+                                      DCHECK(to_return);
+                                      *to_return = soonest_wakeup_delta;
+                                    },
+                                    &to_return));
+    browser_thread_bundle_.RunUntilIdle();
+    return to_return;
+  }
+
+ protected:
+  TestBrowserClient browser_client_;
+  ContentBrowserClient* original_client_;
+  TestBrowserThreadBundle browser_thread_bundle_;
+  TestBrowserContext test_browser_context_;
+};
+
+// Tests that we pick the correct wake up delta for the one-shot Background
+// Sync wake up task, across all storage partitions.
+TEST_F(BackgroundSyncLauncherTest, CorrectSoonestWakeupDeltaIsPicked) {
+  std::vector<GURL> urls = {GURL(kUrl_1), GURL(kUrl_2)};
+
+  // Add two storage partitions. Verify that we set the soonest wake up delta
+  // to base::TimeDelta::Max(). This will cause cancellation of the wakeup
+  // task.
+  SetUpBrowserContext(urls);
+  EXPECT_TRUE(GetSoonestWakeupDelta().is_max());
+
+  // Add two more storage partitions, this time with wakeup_deltas.
+  // Verify that we pick the smaller of the two.
+  int delta_ms = 0;
+  std::map<GURL, int> wakeup_deltas;
+  for (const auto& url : urls)
+    wakeup_deltas[url] = delta_ms += 1000;
+  SetUpBrowserContext(urls, wakeup_deltas);
+
+  EXPECT_EQ(GetSoonestWakeupDelta().InMilliseconds(), 1000);
+}
+
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index b7f7d0a..de713b19 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
 
 #if defined(OS_ANDROID)
 #include "content/browser/android/background_sync_network_observer_android.h"
@@ -42,6 +43,10 @@
 
 namespace {
 
+// The only allowed value of min_interval for one shot Background Sync
+// registrations.
+constexpr int kMinIntervalForOneShotSync = -1;
+
 // The key used to index the background sync data in ServiceWorkerStorage.
 const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData";
 
@@ -117,15 +122,13 @@
 }
 
 void RunInBackgroundOnUIThread(
-    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
-    bool enabled,
-    int64_t min_ms) {
+    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BackgroundSyncController* background_sync_controller =
       GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
   if (background_sync_controller) {
-    background_sync_controller->RunInBackground(enabled, min_ms);
+    background_sync_controller->RunInBackground();
   }
 }
 
@@ -172,6 +175,12 @@
   std::move(task).Run(std::move(callback));
 }
 
+blink::mojom::BackgroundSyncType GetBackgroundSyncType(
+    const blink::mojom::SyncRegistrationOptions& options) {
+  return options.min_interval >= 0 ? blink::mojom::BackgroundSyncType::PERIODIC
+                                   : blink::mojom::BackgroundSyncType::ONE_SHOT;
+}
+
 }  // namespace
 
 BackgroundSyncManager::BackgroundSyncRegistrations::
@@ -213,6 +222,13 @@
     return;
   }
 
+  if (options.min_interval < 0 &&
+      options.min_interval != kMinIntervalForOneShotSync) {
+    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
+                              std::move(callback));
+    return;
+  }
+
   op_scheduler_.ScheduleOperation(
       CacheStorageSchedulerOp::kBackgroundSync,
       base::BindOnce(&BackgroundSyncManager::RegisterCheckIfHasMainFrame,
@@ -221,8 +237,10 @@
                      op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
 }
 
-void BackgroundSyncManager::DidResolveRegistration(int64_t sw_registration_id,
-                                                   const std::string& tag) {
+void BackgroundSyncManager::DidResolveRegistration(
+    int64_t sw_registration_id,
+    const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (disabled_)
@@ -230,7 +248,8 @@
   op_scheduler_.ScheduleOperation(
       CacheStorageSchedulerOp::kBackgroundSync,
       base::BindOnce(&BackgroundSyncManager::DidResolveRegistrationImpl,
-                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id, tag));
+                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id, tag,
+                     sync_type));
 }
 
 void BackgroundSyncManager::GetRegistrations(
@@ -402,7 +421,6 @@
 
   if (status != blink::ServiceWorkerStatusCode::kOk &&
       status != blink::ServiceWorkerStatusCode::kErrorNotFound) {
-    LOG(ERROR) << "BackgroundSync failed to init due to backend failure.";
     DisableAndClearManager(std::move(callback));
     return;
   }
@@ -415,17 +433,29 @@
       registrations->origin =
           url::Origin::Create(GURL(registrations_proto.origin()));
 
-      for (int i = 0, max = registrations_proto.registration_size(); i < max;
-           ++i) {
-        const BackgroundSyncRegistrationProto& registration_proto =
-            registrations_proto.registration(i);
-
+      for (const auto& registration_proto :
+           registrations_proto.registration()) {
+        blink::mojom::BackgroundSyncType sync_type =
+            registration_proto.has_periodic_sync_options()
+                ? blink::mojom::BackgroundSyncType::PERIODIC
+                : blink::mojom::BackgroundSyncType::ONE_SHOT;
         BackgroundSyncRegistration* registration =
-            &registrations->registration_map[registration_proto.tag()];
+            &registrations
+                 ->registration_map[{registration_proto.tag(), sync_type}];
 
         blink::mojom::SyncRegistrationOptions* options =
             registration->options();
         options->tag = registration_proto.tag();
+        if (sync_type == blink::mojom::BackgroundSyncType::PERIODIC) {
+          options->min_interval =
+              registration_proto.periodic_sync_options().min_interval();
+          if (options->min_interval < 0) {
+            DisableAndClearManager(std::move(callback));
+            return;
+          }
+        } else {
+          options->min_interval = kMinIntervalForOneShotSync;
+        }
 
         registration->set_num_attempts(registration_proto.num_attempts());
         registration->set_delay_until(
@@ -534,14 +564,15 @@
     return;
   }
 
+  // TODO(crbug.com/925297): Record Periodic Sync metrics.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(
           &NotifyBackgroundSyncRegisteredOnUIThread, service_worker_context_,
           url::Origin::Create(sw_registration->scope().GetOrigin())));
 
-  BackgroundSyncRegistration* existing_registration =
-      LookupActiveRegistration(sw_registration_id, options.tag);
+  BackgroundSyncRegistration* existing_registration = LookupActiveRegistration(
+      sw_registration_id, options.tag, GetBackgroundSyncType(options));
   if (existing_registration) {
     DCHECK(existing_registration->options()->Equals(options));
 
@@ -639,7 +670,8 @@
 
 BackgroundSyncRegistration* BackgroundSyncManager::LookupActiveRegistration(
     int64_t sw_registration_id,
-    const std::string& tag) {
+    const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   auto it = active_registrations_.find(sw_registration_id);
@@ -649,7 +681,8 @@
   BackgroundSyncRegistrations& registrations = it->second;
   DCHECK(!registrations.origin.opaque());
 
-  auto key_and_registration_iter = registrations.registration_map.find(tag);
+  auto key_and_registration_iter =
+      registrations.registration_map.find({tag, sync_type});
   if (key_and_registration_iter == registrations.registration_map.end())
     return nullptr;
 
@@ -673,6 +706,10 @@
     BackgroundSyncRegistrationProto* registration_proto =
         registrations_proto.add_registration();
     registration_proto->set_tag(registration.options()->tag);
+    if (registration.options()->min_interval >= 0) {
+      registration_proto->mutable_periodic_sync_options()->set_min_interval(
+          registration.options()->min_interval);
+    }
     registration_proto->set_num_attempts(registration.num_attempts());
     registration_proto->set_delay_until(
         registration.delay_until().ToInternalValue());
@@ -729,10 +766,12 @@
 
 void BackgroundSyncManager::DidResolveRegistrationImpl(
     int64_t sw_registration_id,
-    const std::string& tag) {
+    const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
   BackgroundSyncRegistration* registration =
-      LookupActiveRegistration(sw_registration_id, tag);
+      LookupActiveRegistration(sw_registration_id, tag, sync_type);
   if (!registration) {
     // There might not be a registration if the client ack's a registration that
     // was a duplicate in the first place and was already firing and finished by
@@ -746,15 +785,17 @@
   op_scheduler_.CompleteOperationAndRunNext();
 }
 
-void BackgroundSyncManager::RemoveActiveRegistration(int64_t sw_registration_id,
-                                                     const std::string& tag) {
+void BackgroundSyncManager::RemoveActiveRegistration(
+    int64_t sw_registration_id,
+    const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(LookupActiveRegistration(sw_registration_id, tag));
+  DCHECK(LookupActiveRegistration(sw_registration_id, tag, sync_type));
 
   BackgroundSyncRegistrations* registrations =
       &active_registrations_[sw_registration_id];
 
-  registrations->registration_map.erase(tag);
+  registrations->registration_map.erase({tag, sync_type});
 }
 
 void BackgroundSyncManager::AddActiveRegistration(
@@ -767,10 +808,14 @@
       &active_registrations_[sw_registration_id];
   registrations->origin = origin;
 
-  registrations->registration_map[sync_registration.options()->tag] =
+  blink::mojom::BackgroundSyncType sync_type =
+      GetBackgroundSyncType(*sync_registration.options());
+  registrations
+      ->registration_map[{sync_registration.options()->tag, sync_type}] =
       sync_registration;
 
-  if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC)) {
+  if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC) &&
+      sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT) {
     devtools_context_->LogBackgroundServiceEvent(
         sw_registration_id, origin, devtools::proto::BACKGROUND_SYNC,
         /* event_name= */ "Registered Sync",
@@ -875,9 +920,9 @@
 
   if (it != active_registrations_.end()) {
     const BackgroundSyncRegistrations& registrations = it->second;
-    for (const auto& tag_and_registration : registrations.registration_map) {
+    for (const auto& key_and_registration : registrations.registration_map) {
       const BackgroundSyncRegistration& registration =
-          tag_and_registration.second;
+          key_and_registration.second;
       out_registrations.push_back(
           std::make_unique<BackgroundSyncRegistration>(registration));
     }
@@ -915,10 +960,10 @@
   return AreOptionConditionsMet();
 }
 
-void BackgroundSyncManager::RunInBackgroundIfNecessary() {
+base::TimeDelta BackgroundSyncManager::GetSoonestWakeupDelta() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
 
+  base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
   for (const auto& sw_id_and_registrations : active_registrations_) {
     for (const auto& key_and_registration :
          sw_id_and_registrations.second.registration_map) {
@@ -945,6 +990,14 @@
     soonest_wakeup_delta = parameters_->min_sync_recovery_time;
   }
 
+  return soonest_wakeup_delta;
+}
+
+void BackgroundSyncManager::RunInBackgroundIfNecessary() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  base::TimeDelta soonest_wakeup_delta = GetSoonestWakeupDelta();
+
   // Try firing again after the wakeup delta.
   if (!soonest_wakeup_delta.is_max() && !soonest_wakeup_delta.is_zero()) {
     delayed_sync_task_.Reset(base::Bind(&BackgroundSyncManager::FireReadyEvents,
@@ -953,14 +1006,11 @@
   }
 
   // In case the browser closes (or to prevent it from closing), call
-  // RunInBackground to either wake up the browser at the wakeup delta or to
-  // keep the browser running.
+  // RunInBackground to wake up the browser at the soonest wakeup delta across
+  // all the storage partitions.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(
-          RunInBackgroundOnUIThread, service_worker_context_,
-          !soonest_wakeup_delta.is_max() /* should run in background */,
-          soonest_wakeup_delta.InMilliseconds()));
+      base::BindOnce(RunInBackgroundOnUIThread, service_worker_context_));
 }
 
 void BackgroundSyncManager::FireReadyEvents() {
@@ -992,17 +1042,33 @@
   }
 
   // Find the registrations that are ready to run.
-  std::vector<std::pair<int64_t, std::string>> sw_id_and_tags_to_fire;
+  struct RegistrationsToFire {
+    RegistrationsToFire(int64_t service_worker_registration_id_,
+                        std::string tag_,
+                        blink::mojom::BackgroundSyncType sync_type_)
+        : service_worker_registration_id(service_worker_registration_id_),
+          tag(tag_),
+          sync_type(sync_type_) {}
+    int64_t service_worker_registration_id;
+    std::string tag;
+    blink::mojom::BackgroundSyncType sync_type;
+  };
+  std::vector<RegistrationsToFire> to_fire;
 
   for (auto& sw_id_and_registrations : active_registrations_) {
-    const int64_t service_worker_id = sw_id_and_registrations.first;
+    const int64_t service_worker_registration_id =
+        sw_id_and_registrations.first;
     for (auto& key_and_registration :
          sw_id_and_registrations.second.registration_map) {
       BackgroundSyncRegistration* registration = &key_and_registration.second;
 
-      if (IsRegistrationReadyToFire(*registration, service_worker_id)) {
-        sw_id_and_tags_to_fire.push_back(
-            std::make_pair(service_worker_id, key_and_registration.first));
+      if (IsRegistrationReadyToFire(*registration,
+                                    service_worker_registration_id)) {
+        to_fire.emplace_back(
+            service_worker_registration_id,
+            /* tag= */ key_and_registration.first.first,
+            /* sync_type= */ key_and_registration.first.second);
+
         // The state change is not saved to persistent storage because
         // if the sync event is killed mid-sync then it should return to
         // SYNC_STATE_PENDING.
@@ -1011,7 +1077,7 @@
     }
   }
 
-  if (sw_id_and_tags_to_fire.empty()) {
+  if (to_fire.empty()) {
     RunInBackgroundIfNecessary();
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                   std::move(callback));
@@ -1023,36 +1089,39 @@
   // Fire the sync event of the ready registrations and run |callback| once
   // they're all done.
   base::RepeatingClosure events_fired_barrier_closure = base::BarrierClosure(
-      sw_id_and_tags_to_fire.size(),
+      to_fire.size(),
       base::BindOnce(&BackgroundSyncManager::FireReadyEventsAllEventsFiring,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 
   // Record the total time taken after all events have run to completion.
   base::RepeatingClosure events_completed_barrier_closure =
-      base::BarrierClosure(sw_id_and_tags_to_fire.size(),
+      base::BarrierClosure(to_fire.size(),
                            base::BindOnce(&OnAllSyncEventsCompleted, start_time,
-                                          sw_id_and_tags_to_fire.size()));
+                                          to_fire.size()));
 
-  for (const auto& sw_id_and_tag : sw_id_and_tags_to_fire) {
-    int64_t service_worker_id = sw_id_and_tag.first;
-    const BackgroundSyncRegistration* registration =
-        LookupActiveRegistration(service_worker_id, sw_id_and_tag.second);
+  for (auto& registration_info : to_fire) {
+    const BackgroundSyncRegistration* registration = LookupActiveRegistration(
+        registration_info.service_worker_registration_id, registration_info.tag,
+        registration_info.sync_type);
     DCHECK(registration);
 
     service_worker_context_->FindReadyRegistrationForId(
-        service_worker_id,
-        active_registrations_[service_worker_id].origin.GetURL(),
+        registration_info.service_worker_registration_id,
+        active_registrations_[registration_info.service_worker_registration_id]
+            .origin.GetURL(),
         base::BindOnce(
             &BackgroundSyncManager::FireReadyEventsDidFindRegistration,
-            weak_ptr_factory_.GetWeakPtr(), service_worker_id,
-            sw_id_and_tag.second, events_fired_barrier_closure,
-            events_completed_barrier_closure));
+            weak_ptr_factory_.GetWeakPtr(),
+            registration_info.service_worker_registration_id,
+            std::move(registration_info.tag), registration_info.sync_type,
+            events_fired_barrier_closure, events_completed_barrier_closure));
   }
 }
 
 void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
     int64_t service_worker_id,
     const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type,
     base::OnceClosure event_fired_callback,
     base::OnceClosure event_completed_callback,
     blink::ServiceWorkerStatusCode service_worker_status,
@@ -1060,7 +1129,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   BackgroundSyncRegistration* registration =
-      LookupActiveRegistration(service_worker_id, tag);
+      LookupActiveRegistration(service_worker_id, tag, sync_type);
 
   if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
     if (registration)
@@ -1075,6 +1144,19 @@
   DCHECK_EQ(service_worker_id, service_worker_registration->id());
   DCHECK(registration);
 
+  // Don't dispatch a sync event if the sync is periodic.
+  // TODO(crbug.com/925297): Remove this code when we've added the logic to
+  // dispatch periodic sync events.
+  if (registration && sync_type == blink::mojom::BackgroundSyncType::PERIODIC) {
+    RemoveActiveRegistration(service_worker_id, tag, sync_type);
+    StoreRegistrations(service_worker_id, base::DoNothing());
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, std::move(event_fired_callback));
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, std::move(event_completed_callback));
+    return;
+  }
+
   const bool option_conditions_met = AreOptionConditionsMet();
   UMA_HISTOGRAM_BOOLEAN("BackgroundSync.OptionConditionsChanged",
                         !option_conditions_met);
@@ -1099,13 +1181,13 @@
       url::Origin::Create(service_worker_registration->scope().GetOrigin()),
       base::BindOnce(&BackgroundSyncMetrics::RecordEventStarted));
 
-  DispatchSyncEvent(registration->options()->tag,
-                    service_worker_registration->active_version(), last_chance,
-                    base::BindOnce(&BackgroundSyncManager::EventComplete,
-                                   weak_ptr_factory_.GetWeakPtr(),
-                                   service_worker_registration,
-                                   service_worker_registration->id(), tag,
-                                   std::move(event_completed_callback)));
+  DispatchSyncEvent(
+      registration->options()->tag,
+      service_worker_registration->active_version(), last_chance,
+      base::BindOnce(
+          &BackgroundSyncManager::EventComplete, weak_ptr_factory_.GetWeakPtr(),
+          service_worker_registration, service_worker_registration->id(), tag,
+          sync_type, std::move(event_completed_callback)));
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, std::move(event_fired_callback));
@@ -1125,6 +1207,7 @@
     scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
     int64_t service_worker_id,
     const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type,
     base::OnceClosure callback,
     blink::ServiceWorkerStatusCode status_code) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1139,13 +1222,14 @@
       CacheStorageSchedulerOp::kBackgroundSync,
       base::BindOnce(&BackgroundSyncManager::EventCompleteImpl,
                      weak_ptr_factory_.GetWeakPtr(), service_worker_id, tag,
-                     status_code,
+                     sync_type, status_code,
                      op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
 }
 
 void BackgroundSyncManager::EventCompleteImpl(
     int64_t service_worker_id,
     const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type,
     blink::ServiceWorkerStatusCode status_code,
     base::OnceClosure callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1159,7 +1243,7 @@
   num_firing_registrations_ -= 1;
 
   BackgroundSyncRegistration* registration =
-      LookupActiveRegistration(service_worker_id, tag);
+      LookupActiveRegistration(service_worker_id, tag, sync_type);
   if (!registration) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                   std::move(callback));
@@ -1202,7 +1286,8 @@
     registration->set_delay_until(clock_->Now() + delay);
     registration_completed = false;
 
-    if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC)) {
+    if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC) &&
+        sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT) {
       devtools_context_->LogBackgroundServiceEvent(
           sw_registration->id(), origin, devtools::proto::BACKGROUND_SYNC,
           /* event_name= */ "Sync Event Failed",
@@ -1214,9 +1299,10 @@
   }
 
   if (registration_completed) {
-    RemoveActiveRegistration(service_worker_id, tag);
+    RemoveActiveRegistration(service_worker_id, tag, sync_type);
 
-    if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC)) {
+    if (devtools_context_->IsRecording(devtools::proto::BACKGROUND_SYNC) &&
+        sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT) {
       bool succeded = status_code == blink::ServiceWorkerStatusCode::kOk;
       devtools_context_->LogBackgroundServiceEvent(
           sw_registration->id(), origin, devtools::proto::BACKGROUND_SYNC,
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h
index 14e4923..19f9917 100644
--- a/content/browser/background_sync/background_sync_manager.h
+++ b/content/browser/background_sync/background_sync_manager.h
@@ -82,7 +82,8 @@
   // Called after the client has resolved its registration promise. At this
   // point it's safe to fire any pending registrations.
   void DidResolveRegistration(int64_t sw_registration_id,
-                              const std::string& tag);
+                              const std::string& tag,
+                              blink::mojom::BackgroundSyncType sync_type);
 
   // Finds the background sync registrations associated with
   // |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
@@ -123,6 +124,10 @@
   // Once all of this is done, invokes |callback|.
   void FireReadyEventsThenRunCallback(base::OnceClosure callback);
 
+  // Gets the soonest delta after which the browser should be woken up to send
+  // a Background Sync event. If set to max, the browser won't be woken up.
+  virtual base::TimeDelta GetSoonestWakeupDelta();
+
  protected:
   BackgroundSyncManager(
       scoped_refptr<ServiceWorkerContextWrapper> context,
@@ -156,7 +161,9 @@
   friend class BackgroundSyncManagerTest;
 
   struct BackgroundSyncRegistrations {
-    using RegistrationMap = std::map<std::string, BackgroundSyncRegistration>;
+    using RegistrationMap =
+        std::map<std::pair<std::string, blink::mojom::BackgroundSyncType>,
+                 BackgroundSyncRegistration>;
 
     BackgroundSyncRegistrations();
     BackgroundSyncRegistrations(const BackgroundSyncRegistrations& other);
@@ -186,7 +193,8 @@
   // Returns the existing registration or nullptr if it cannot be found.
   BackgroundSyncRegistration* LookupActiveRegistration(
       int64_t sw_registration_id,
-      const std::string& tag);
+      const std::string& tag,
+      blink::mojom::BackgroundSyncType sync_type);
 
   // Write all registrations for a given |sw_registration_id| to persistent
   // storage.
@@ -195,7 +203,8 @@
 
   // Removes the active registration if it is in the map.
   void RemoveActiveRegistration(int64_t sw_registration_id,
-                                const std::string& tag);
+                                const std::string& tag,
+                                blink::mojom::BackgroundSyncType sync_type);
 
   void AddActiveRegistration(
       int64_t sw_registration_id,
@@ -236,7 +245,8 @@
 
   // DidResolveRegistration callbacks
   void DidResolveRegistrationImpl(int64_t sw_registration_id,
-                                  const std::string& tag);
+                                  const std::string& tag,
+                                  blink::mojom::BackgroundSyncType sync_type);
 
   // GetRegistrations callbacks
   void GetRegistrationsImpl(int64_t sw_registration_id,
@@ -263,6 +273,7 @@
   void FireReadyEventsDidFindRegistration(
       int64_t service_worker_id,
       const std::string& tag,
+      blink::mojom::BackgroundSyncType sync_type,
       base::OnceClosure event_fired_callback,
       base::OnceClosure event_completed_callback,
       blink::ServiceWorkerStatusCode service_worker_status,
@@ -274,10 +285,12 @@
       scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
       int64_t service_worker_id,
       const std::string& tag,
+      blink::mojom::BackgroundSyncType sync_type,
       base::OnceClosure callback,
       blink::ServiceWorkerStatusCode status_code);
   void EventCompleteImpl(int64_t service_worker_id,
                          const std::string& tag,
+                         blink::mojom::BackgroundSyncType sync_type,
                          blink::ServiceWorkerStatusCode status_code,
                          base::OnceClosure callback);
   void EventCompleteDidStore(int64_t service_worker_id,
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
index 70fb93b..b6c3d96 100644
--- a/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -50,8 +50,8 @@
 
 namespace {
 
-using ::testing::Return;
 using ::testing::_;
+using ::testing::Return;
 
 const char kScope1[] = "https://example.com/a";
 const char kScope2[] = "https://example.com/b";
@@ -84,6 +84,12 @@
   *called = true;
 }
 
+blink::mojom::BackgroundSyncType GetBackgroundSyncType(
+    const blink::mojom::SyncRegistrationOptions& options) {
+  return options.min_interval >= 0 ? blink::mojom::BackgroundSyncType::PERIODIC
+                                   : blink::mojom::BackgroundSyncType::ONE_SHOT;
+}
+
 }  // namespace
 
 class BackgroundSyncManagerTest
@@ -270,6 +276,7 @@
       blink::mojom::SyncRegistrationOptions options) {
     bool was_called = false;
     const std::string tag = options.tag;
+    blink::mojom::BackgroundSyncType sync_type = GetBackgroundSyncType(options);
     background_sync_manager_->Register(
         sw_registration_id, std::move(options),
         base::BindOnce(
@@ -281,7 +288,8 @@
     // Mock the client receiving the response and calling
     // DidResolveRegistration.
     if (callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
-      background_sync_manager_->DidResolveRegistration(sw_registration_id, tag);
+      background_sync_manager_->DidResolveRegistration(sw_registration_id, tag,
+                                                       sync_type);
       base::RunLoop().RunUntilIdle();
     }
 
@@ -314,7 +322,7 @@
     if (callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
       for (auto iter = callback_registrations_.begin();
            iter < callback_registrations_.end(); ++iter) {
-        if ((*iter)->options()->tag == registration_options.tag) {
+        if ((*iter)->options()->Equals(registration_options)) {
           // Transfer the matching registration out of the vector into
           // callback_registration_ for testing.
           callback_registration_ = std::move(*iter);
@@ -464,6 +472,11 @@
   EXPECT_TRUE(Register(sync_options_1_));
 }
 
+TEST_F(BackgroundSyncManagerTest, FailToRegisterWithInvalidOptions) {
+  sync_options_1_.min_interval = -2000;
+  EXPECT_FALSE(Register(sync_options_1_));
+}
+
 TEST_F(BackgroundSyncManagerTest, RegisterAndWaitToFireUntilResolved) {
   InitSyncEventTest();
   bool was_called = false;
@@ -478,8 +491,9 @@
   // client to acknowledge with DidResolveRegistration.
   EXPECT_EQ(0, sync_events_called_);
 
-  background_sync_manager_->DidResolveRegistration(sw_registration_id_1_,
-                                                   sync_options_1_.tag);
+  background_sync_manager_->DidResolveRegistration(
+      sw_registration_id_1_, sync_options_1_.tag,
+      GetBackgroundSyncType(sync_options_1_));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, sync_events_called_);
 }
@@ -499,8 +513,9 @@
   EXPECT_EQ(0, sync_events_called_);
 
   // Resolve a non-existing registration.
-  background_sync_manager_->DidResolveRegistration(sw_registration_id_1_,
-                                                   "unknown_tag");
+  background_sync_manager_->DidResolveRegistration(
+      sw_registration_id_1_, "unknown_tag",
+      GetBackgroundSyncType(sync_options_1_));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, sync_events_called_);
 }
@@ -835,6 +850,30 @@
   EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
 }
 
+TEST_F(BackgroundSyncManagerTest, PeriodicSyncOptions) {
+  sync_options_1_.min_interval = 2;
+  EXPECT_TRUE(Register(sync_options_1_));
+  EXPECT_TRUE(GetRegistration(sync_options_1_));
+  EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
+}
+
+TEST_F(BackgroundSyncManagerTest, BothTypesOfSyncShareATag) {
+  sync_options_1_.tag = "foo";
+  sync_options_2_.tag = "foo";
+  // Make the registration periodic.
+  sync_options_2_.min_interval = 36000;
+
+  EXPECT_TRUE(Register(sync_options_1_));
+  EXPECT_TRUE(GetRegistration(sync_options_1_));
+  EXPECT_EQ(callback_registration_->options()->tag, "foo");
+  EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
+
+  EXPECT_TRUE(Register(sync_options_2_));
+  EXPECT_TRUE(GetRegistration(sync_options_2_));
+  EXPECT_TRUE(sync_options_2_.Equals(*callback_registration_->options()));
+  EXPECT_EQ(callback_registration_->options()->tag, "foo");
+}
+
 TEST_F(BackgroundSyncManagerTest, FiresOnRegistration) {
   InitSyncEventTest();
 
@@ -843,6 +882,21 @@
   EXPECT_FALSE(GetRegistration(sync_options_1_));
 }
 
+// TODO(crbug.com/925297): Update once we support dispatching periodic sync
+// events.
+TEST_F(BackgroundSyncManagerTest, PeriodicSyncDoesNotFireOnRegistration) {
+  InitSyncEventTest();
+  sync_options_2_.min_interval = 36000;
+
+  EXPECT_TRUE(Register(sync_options_1_));
+  EXPECT_EQ(1, sync_events_called_);
+  EXPECT_FALSE(GetRegistration(sync_options_1_));
+
+  EXPECT_TRUE(Register(sync_options_2_));
+  EXPECT_EQ(1, sync_events_called_);  // no increase.
+  EXPECT_FALSE(GetRegistration(sync_options_2_));
+}
+
 TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptFails) {
   InitDelayedSyncEventTest();
   RegisterAndVerifySyncEventDelayed(sync_options_1_);
@@ -1200,30 +1254,29 @@
   // The BackgroundSyncManager should declare in initialization
   // that it doesn't need to be woken up since it has no registrations.
   EXPECT_LT(0, GetController()->run_in_background_count());
-  EXPECT_FALSE(GetController()->run_in_background_enabled());
+  EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
 
   SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
-  EXPECT_FALSE(GetController()->run_in_background_enabled());
+  EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
 
   // Register a one-shot but it can't fire due to lack of network, wake up is
   // required.
   Register(sync_options_1_);
-  EXPECT_TRUE(GetController()->run_in_background_enabled());
+  EXPECT_TRUE(test_background_sync_manager_->IsBrowserWakeupScheduled());
 
   // Start the event but it will pause mid-sync due to
   // InitDelayedSyncEventTest() above.
   SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
-  EXPECT_TRUE(GetController()->run_in_background_enabled());
-  EXPECT_EQ(test_background_sync_manager_->background_sync_parameters()
-                ->min_sync_recovery_time,
-            base::TimeDelta::FromMilliseconds(
-                GetController()->run_in_background_min_ms()));
+  EXPECT_TRUE(test_background_sync_manager_->IsBrowserWakeupScheduled());
+  EXPECT_TRUE(test_background_sync_manager_->EqualsSoonestWakeupDelta(
+      test_background_sync_manager_->background_sync_parameters()
+          ->min_sync_recovery_time));
 
   // Finish the sync.
   ASSERT_TRUE(sync_fired_callback_);
   std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(GetController()->run_in_background_enabled());
+  EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
 }
 
 TEST_F(BackgroundSyncManagerTest, OneAttempt) {
diff --git a/content/browser/background_sync/background_sync_service_impl.cc b/content/browser/background_sync/background_sync_service_impl.cc
index 678a828..e64b103 100644
--- a/content/browser/background_sync/background_sync_service_impl.cc
+++ b/content/browser/background_sync/background_sync_service_impl.cc
@@ -76,13 +76,15 @@
 
 void BackgroundSyncServiceImpl::DidResolveRegistration(
     int64_t sw_registration_id,
-    const std::string& tag) {
+    const std::string& tag,
+    blink::mojom::BackgroundSyncType sync_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   BackgroundSyncManager* background_sync_manager =
       background_sync_context_->background_sync_manager();
   DCHECK(background_sync_manager);
-  background_sync_manager->DidResolveRegistration(sw_registration_id, tag);
+  background_sync_manager->DidResolveRegistration(sw_registration_id, tag,
+                                                  sync_type);
 }
 
 void BackgroundSyncServiceImpl::GetRegistrations(
@@ -113,7 +115,7 @@
 
   DCHECK(result);
   blink::mojom::SyncRegistrationOptionsPtr mojo_options =
-      blink::mojom::SyncRegistrationOptions::New(result->options()->tag);
+      blink::mojom::SyncRegistrationOptions::New(*result->options());
   std::move(callback).Run(
       static_cast<blink::mojom::BackgroundSyncError>(status),
       std::move(mojo_options));
@@ -127,9 +129,10 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   std::vector<blink::mojom::SyncRegistrationOptionsPtr> mojo_registrations;
-  for (const auto& registration : result_registrations)
-    mojo_registrations.push_back(blink::mojom::SyncRegistrationOptions::New(
-        registration->options()->tag));
+  for (const auto& registration : result_registrations) {
+    mojo_registrations.push_back(
+        blink::mojom::SyncRegistrationOptions::New(*registration->options()));
+  }
 
   std::move(callback).Run(
       static_cast<blink::mojom::BackgroundSyncError>(status),
diff --git a/content/browser/background_sync/background_sync_service_impl.h b/content/browser/background_sync/background_sync_service_impl.h
index d044a62158..e064e96f 100644
--- a/content/browser/background_sync/background_sync_service_impl.h
+++ b/content/browser/background_sync/background_sync_service_impl.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/containers/id_map.h"
@@ -37,8 +38,10 @@
   void Register(blink::mojom::SyncRegistrationOptionsPtr options,
                 int64_t sw_registration_id,
                 RegisterCallback callback) override;
-  void DidResolveRegistration(int64_t sw_registration_id,
-                              const std::string& tag) override;
+  void DidResolveRegistration(
+      int64_t sw_registration_id,
+      const std::string& tag,
+      blink::mojom::BackgroundSyncType sync_type) override;
   void GetRegistrations(int64_t sw_registration_id,
                         GetRegistrationsCallback callback) override;
 
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn
index f14e719..2250166 100644
--- a/content/browser/devtools/BUILD.gn
+++ b/content/browser/devtools/BUILD.gn
@@ -129,3 +129,16 @@
     "devtools_background_services.proto",
   ]
 }
+
+source_set("inspector_protocol_encoding_test") {
+  testonly = true
+  sources = [
+    "../../../third_party/inspector_protocol/encoding/encoding_test.cc",
+  ]
+  deps = [
+    "//base",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/inspector_protocol:encoding",
+  ]
+}
diff --git a/content/browser/devtools/DEPS b/content/browser/devtools/DEPS
index 93bf7150..962e548 100644
--- a/content/browser/devtools/DEPS
+++ b/content/browser/devtools/DEPS
@@ -3,4 +3,7 @@
   "+content/shell/browser/shell.h", # for access to web contents from devtools_protocol_test_support.cc
   # V8 version info
   "+v8/include/v8-version-string.h",
+
+  # For converting between JSON and CBOR in devtools_session_encoding.cc.
+  "+third_party/inspector_protocol/encoding",
 ]
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc
index 2862801..e491560 100644
--- a/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -88,7 +88,7 @@
         socket_callback_, tethering_task_runner_));
   }
   session->AddHandler(std::make_unique<protocol::TracingHandler>(
-      nullptr, GetIOContext(), session->client()->UsesBinaryProtocol()));
+      nullptr, GetIOContext(), session->UsesBinaryProtocol()));
   return true;
 }
 
diff --git a/content/browser/devtools/devtools_session.cc b/content/browser/devtools/devtools_session.cc
index 75d2d42..c88086c 100644
--- a/content/browser/devtools/devtools_session.cc
+++ b/content/browser/devtools/devtools_session.cc
@@ -4,10 +4,11 @@
 
 #include "content/browser/devtools/devtools_session.h"
 
+#include <vector>
+
 #include "base/bind.h"
-#include "base/json/json_reader.h"
-#include "base/strings/stringprintf.h"
 #include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/devtools/devtools_session_encoding.h"
 #include "content/browser/devtools/protocol/devtools_domain_handler.h"
 #include "content/browser/devtools/protocol/protocol.h"
 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -34,7 +35,6 @@
 static const char kMethod[] = "method";
 static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger";
 static const char kSessionId[] = "sessionId";
-
 }  // namespace
 
 DevToolsSession::DevToolsSession(DevToolsAgentHostClient* client)
@@ -73,6 +73,11 @@
   return root_session_ ? root_session_ : this;
 }
 
+bool DevToolsSession::UsesBinaryProtocol() const {
+  return client_->UsesBinaryProtocol() ||
+         EnableInternalDevToolsBinaryProtocol();
+}
+
 void DevToolsSession::AddHandler(
     std::unique_ptr<protocol::DevToolsDomainHandler> handler) {
   DCHECK(agent_host_);
@@ -133,10 +138,27 @@
   io_session_ptr_.reset();
 }
 
+// The client of the devtools session will call this method to send a message
+// to handlers / agents that the session is connected with.
 bool DevToolsSession::DispatchProtocolMessage(const std::string& message) {
+  std::string converted_cbor_message;
+  const std::string* message_to_send = &message;
+  if (EnableInternalDevToolsBinaryProtocol()) {
+    if (client_->UsesBinaryProtocol()) {
+      // If the client uses the binary protocol, then |message| is already
+      // CBOR (it comes from the client).
+      DCHECK(IsCBOR(message));
+    } else {
+      converted_cbor_message = ConvertJSONToCBOR(message);
+      message_to_send = &converted_cbor_message;
+    }
+  }
   if (proxy_delegate_) {
-    // Note: we assume that child sessions are not forwarding.
-    proxy_delegate_->SendMessageToBackend(this, message);
+    // TODO(dgozman): revisit the proxy delegate.
+    // TODO(johannes): Should we send CBOR to an external backend? Maybe not!
+    // Revisit this when EnableInternalDevToolsBinaryProtocol() is on
+    // unconditionally.  Note: we assume that child sessions are not forwarding.
+    proxy_delegate_->SendMessageToBackend(this, *message_to_send);
     return true;
   }
 
@@ -146,14 +168,15 @@
 
   std::string session_id;
   if (!value || !value->getString(kSessionId, &session_id))
-    return DispatchProtocolMessageInternal(message, std::move(value));
+    return DispatchProtocolMessageInternal(*message_to_send, std::move(value));
 
   auto it = child_sessions_.find(session_id);
   if (it == child_sessions_.end())
     return false;
   DevToolsSession* session = it->second;
   DCHECK(!session->proxy_delegate_);
-  return session->DispatchProtocolMessageInternal(message, std::move(value));
+  return session->DispatchProtocolMessageInternal(*message_to_send,
+                                                  std::move(value));
 }
 
 bool DevToolsSession::DispatchProtocolMessageInternal(
@@ -242,34 +265,73 @@
   suspended_messages_.clear();
 }
 
+// The following methods handle responses or notifications coming from
+// the browser to the client.
+static void SendProtocolResponseOrNotification(
+    DevToolsAgentHostClient* client,
+    DevToolsAgentHostImpl* agent_host,
+    std::unique_ptr<protocol::Serializable> message) {
+  if (!EnableInternalDevToolsBinaryProtocol()) {
+    bool binary = client->UsesBinaryProtocol();
+    client->DispatchProtocolMessage(agent_host, message->serialize(binary));
+    return;
+  }
+  std::string cbor = message->serialize(/*binary=*/true);
+  DCHECK(IsCBOR(cbor));
+  client->DispatchProtocolMessage(agent_host, client->UsesBinaryProtocol()
+                                                  ? cbor
+                                                  : ConvertCBORToJSON(cbor));
+}
+
 void DevToolsSession::sendProtocolResponse(
     int call_id,
     std::unique_ptr<protocol::Serializable> message) {
-  bool binary = client_->UsesBinaryProtocol();
-  client_->DispatchProtocolMessage(agent_host_, message->serialize(binary));
+  SendProtocolResponseOrNotification(client_, agent_host_, std::move(message));
   // |this| may be deleted at this point.
 }
 
 void DevToolsSession::sendProtocolNotification(
     std::unique_ptr<protocol::Serializable> message) {
-  bool binary = client_->UsesBinaryProtocol();
-  client_->DispatchProtocolMessage(agent_host_, message->serialize(binary));
+  SendProtocolResponseOrNotification(client_, agent_host_, std::move(message));
   // |this| may be deleted at this point.
 }
 
 void DevToolsSession::flushProtocolNotifications() {
 }
 
+// The following methods handle responses or notifications coming from
+// the renderer (blink) to the client.
+static void DispatchProtocolResponseOrNotification(
+    DevToolsAgentHostClient* client,
+    DevToolsAgentHostImpl* agent_host,
+    blink::mojom::DevToolsMessagePtr message) {
+  // TODO(johannes): When eliminating the
+  // --enable-internal-devtools-binary-protocol flag, reconsider the similarity
+  // with SendProtocolResponseOrNotification above and either merge the methods
+  // or inline them again.
+  if (!EnableInternalDevToolsBinaryProtocol()) {
+    client->DispatchProtocolMessage(
+        agent_host,
+        std::string(reinterpret_cast<const char*>(message->data.data()),
+                    message->data.size()));
+    return;
+  }
+  std::string cbor(reinterpret_cast<const char*>(message->data.data()),
+                   message->data.size());
+  DCHECK(IsCBOR(cbor));
+  client->DispatchProtocolMessage(agent_host, client->UsesBinaryProtocol()
+                                                  ? cbor
+                                                  : ConvertCBORToJSON(cbor));
+}
+
 void DevToolsSession::DispatchProtocolResponse(
     blink::mojom::DevToolsMessagePtr message,
     int call_id,
     blink::mojom::DevToolsSessionStatePtr updates) {
   ApplySessionStateUpdates(std::move(updates));
   waiting_for_response_messages_.erase(call_id);
-  client_->DispatchProtocolMessage(
-      agent_host_,
-      std::string(reinterpret_cast<const char*>(message->data.data()),
-                  message->data.size()));
+  DispatchProtocolResponseOrNotification(client_, agent_host_,
+                                         std::move(message));
   // |this| may be deleted at this point.
 }
 
@@ -277,10 +339,8 @@
     blink::mojom::DevToolsMessagePtr message,
     blink::mojom::DevToolsSessionStatePtr updates) {
   ApplySessionStateUpdates(std::move(updates));
-  client_->DispatchProtocolMessage(
-      agent_host_,
-      std::string(reinterpret_cast<const char*>(message->data.data()),
-                  message->data.size()));
+  DispatchProtocolResponseOrNotification(client_, agent_host_,
+                                         std::move(message));
   // |this| may be deleted at this point.
 }
 
diff --git a/content/browser/devtools/devtools_session.h b/content/browser/devtools/devtools_session.h
index 413d757..619c96e 100644
--- a/content/browser/devtools/devtools_session.h
+++ b/content/browser/devtools/devtools_session.h
@@ -42,6 +42,11 @@
   DevToolsAgentHostClient* client() { return client_; }
   DevToolsSession* GetRootSession();
 
+  // Whether this session uses binary protocol. This is true if
+  // |client()->UsesBinaryProtocol()| or if the
+  // --enable-devtools-binary-protocol flag is set.
+  bool UsesBinaryProtocol() const;
+
   // Browser-only sessions do not talk to mojom::DevToolsAgent, but instead
   // handle all protocol messages locally in the browser process.
   void SetBrowserOnly(bool browser_only);
diff --git a/content/browser/devtools/devtools_session_encoding.cc b/content/browser/devtools/devtools_session_encoding.cc
new file mode 100644
index 0000000..a297b78e0
--- /dev/null
+++ b/content/browser/devtools/devtools_session_encoding.cc
@@ -0,0 +1,94 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_session_encoding.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/public/common/content_switches.h"
+#include "third_party/inspector_protocol/encoding/encoding.h"
+
+using inspector_protocol_encoding::span;
+using inspector_protocol_encoding::Status;
+using inspector_protocol_encoding::StreamingParserHandler;
+using inspector_protocol_encoding::cbor::NewCBOREncoder;
+using inspector_protocol_encoding::cbor::ParseCBOR;
+using inspector_protocol_encoding::json::NewJSONEncoder;
+using inspector_protocol_encoding::json::ParseJSON;
+using inspector_protocol_encoding::json::Platform;
+
+namespace content {
+namespace {
+// ContentShellPlatform allows us to inject the string<->double conversion
+// routines from base:: into the inspector_protocol JSON parser / serializer.
+class ContentShellPlatform : public Platform {
+ public:
+  bool StrToD(const char* str, double* result) const override {
+    return base::StringToDouble(str, result);
+  }
+
+  // Prints |value| in a format suitable for JSON.
+  std::unique_ptr<char[]> DToStr(double value) const override {
+    std::string str = base::NumberToString(value);
+    std::unique_ptr<char[]> result(new char[str.size() + 1]);
+    memcpy(result.get(), str.c_str(), str.size() + 1);
+    return result;
+  }
+};
+}  // namespace
+bool EnableInternalDevToolsBinaryProtocol() {
+  static bool enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableInternalDevToolsBinaryProtocol);
+  return enabled;
+}
+
+// TODO(johannes): Move this into the cbor library. Don't want to
+// do this just yet to first gain more experience about the most
+// appropriate API, including how to propagate errors.
+std::string ConvertCBORToJSON(const std::string& cbor) {
+  ContentShellPlatform platform;
+  std::string json_message;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(&platform, &json_message, &status);
+  ParseCBOR(
+      span<uint8_t>(reinterpret_cast<const uint8_t*>(cbor.data()), cbor.size()),
+      json_writer.get());
+  if (!status.ok()) {
+    LOG(ERROR) << "ConvertCBORToJSON error "
+               << static_cast<uint32_t>(status.error) << " position "
+               << static_cast<uint32_t>(status.pos);
+    return "";
+  }
+  return json_message;
+}
+
+std::string ConvertJSONToCBOR(const std::string& json) {
+  ContentShellPlatform platform;
+  std::vector<uint8_t> cbor;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> encoder =
+      NewCBOREncoder(&cbor, &status);
+  ParseJSON(
+      &platform,
+      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
+      encoder.get());
+  if (!status.ok()) {
+    LOG(ERROR) << "ConvertJSONToCBOR error "
+               << static_cast<uint32_t>(status.error) << " position "
+               << static_cast<uint32_t>(status.pos);
+    return "";
+  }
+  return std::string(cbor.begin(), cbor.end());
+}
+
+bool IsCBOR(const std::string& serialized) {
+  return serialized.size() >= 6 &&
+         reinterpret_cast<const uint8_t&>(serialized[0]) == 0xd8 &&
+         reinterpret_cast<const uint8_t&>(serialized[1]) == 0x5a;
+}
+}  // namespace content
diff --git a/content/browser/devtools/devtools_session_encoding.h b/content/browser/devtools/devtools_session_encoding.h
new file mode 100644
index 0000000..f4bb1ef
--- /dev/null
+++ b/content/browser/devtools/devtools_session_encoding.h
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
+
+#include <string>
+
+namespace content {
+
+// Whether --enable-internal-devtools-binary-parotocol was passed on the command
+// line.  If so, the DevtoolsSession will convert all outgoing traffic to agents
+// / handlers / etc. to the CBOR-based binary protocol.
+bool EnableInternalDevToolsBinaryProtocol();
+
+// Conversion routines between the inspector protocol binary wire format
+// (based on CBOR RFC 7049) and JSON.
+std::string ConvertCBORToJSON(const std::string& cbor);
+std::string ConvertJSONToCBOR(const std::string& json);
+
+// Whether |serialized| is CBOR produced by the inspector protocol.
+// We always enclose messages with an envelope, that is, the 0xd8 tag
+// followed by the indicator for the byte string, followed by a 32 bit
+// length value (4 bytes).
+bool IsCBOR(const std::string& serialized);
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 4fa2f08..cfef102 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -665,12 +665,14 @@
       protocol = "h2";
     } else if (url.SchemeIsHTTPOrHTTPS()) {
       protocol = "http";
-      if (info.headers->GetHttpVersion() == net::HttpVersion(0, 9))
-        protocol = "http/0.9";
-      else if (info.headers->GetHttpVersion() == net::HttpVersion(1, 0))
-        protocol = "http/1.0";
-      else if (info.headers->GetHttpVersion() == net::HttpVersion(1, 1))
-        protocol = "http/1.1";
+      if (info.headers) {
+        if (info.headers->GetHttpVersion() == net::HttpVersion(0, 9))
+          protocol = "http/0.9";
+        else if (info.headers->GetHttpVersion() == net::HttpVersion(1, 0))
+          protocol = "http/1.0";
+        else if (info.headers->GetHttpVersion() == net::HttpVersion(1, 1))
+          protocol = "http/1.1";
+      }
     } else {
       protocol = url.scheme();
     }
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index d88e0a5..b4d72bc 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -306,8 +306,7 @@
   session->AddHandler(std::make_unique<protocol::SecurityHandler>());
   if (!frame_tree_node_ || !frame_tree_node_->parent()) {
     session->AddHandler(std::make_unique<protocol::TracingHandler>(
-        frame_tree_node_, GetIOContext(),
-        session->client()->UsesBinaryProtocol()));
+        frame_tree_node_, GetIOContext(), session->UsesBinaryProtocol()));
   }
 
   if (sessions().empty()) {
diff --git a/content/browser/indexed_db/cursor_impl.cc b/content/browser/indexed_db/cursor_impl.cc
index 23a274e5..687e5cb9 100644
--- a/content/browser/indexed_db/cursor_impl.cc
+++ b/content/browser/indexed_db/cursor_impl.cc
@@ -28,7 +28,9 @@
                 const IndexedDBKey& key,
                 const IndexedDBKey& primary_key,
                 blink::mojom::IDBCursor::CursorContinueCallback callback);
-  void Prefetch(int32_t count, scoped_refptr<IndexedDBCallbacks> callbacks);
+  void Prefetch(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+                int32_t count,
+                blink::mojom::IDBCursor::PrefetchCallback callback);
   void PrefetchReset(int32_t used_prefetches, int32_t unused_prefetches);
 
   void OnRemoveBinding(base::OnceClosure remove_binding_cb);
@@ -73,14 +75,10 @@
                     std::move(callback));
 }
 
-void CursorImpl::Prefetch(
-    int32_t count,
-    blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
+void CursorImpl::Prefetch(int32_t count,
+                          blink::mojom::IDBCursor::PrefetchCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  scoped_refptr<IndexedDBCallbacks> callbacks(
-      new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
-                             std::move(callbacks_info), idb_runner_));
-  helper_->Prefetch(count, std::move(callbacks));
+  helper_->Prefetch(dispatcher_host_->AsWeakPtr(), count, std::move(callback));
 }
 
 void CursorImpl::PrefetchReset(int32_t used_prefetches,
@@ -129,10 +127,12 @@
 }
 
 void CursorImpl::IDBSequenceHelper::Prefetch(
+    base::WeakPtr<content::IndexedDBDispatcherHost> dispatcher_host,
     int32_t count,
-    scoped_refptr<IndexedDBCallbacks> callbacks) {
+    blink::mojom::IDBCursor::PrefetchCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  cursor_->PrefetchContinue(count, std::move(callbacks));
+  cursor_->PrefetchContinue(std::move(dispatcher_host), count,
+                            std::move(callback));
 }
 
 void CursorImpl::IDBSequenceHelper::PrefetchReset(int32_t used_prefetches,
diff --git a/content/browser/indexed_db/cursor_impl.h b/content/browser/indexed_db/cursor_impl.h
index 76a5b64..feb7f89 100644
--- a/content/browser/indexed_db/cursor_impl.h
+++ b/content/browser/indexed_db/cursor_impl.h
@@ -38,7 +38,7 @@
       const blink::IndexedDBKey& primary_key,
       blink::mojom::IDBCursor::CursorContinueCallback callback) override;
   void Prefetch(int32_t count,
-                blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override;
+                blink::mojom::IDBCursor::PrefetchCallback callback) override;
   void PrefetchReset(int32_t used_prefetches,
                      int32_t unused_prefetches) override;
 
diff --git a/content/browser/indexed_db/indexed_db_cursor.cc b/content/browser/indexed_db/indexed_db_cursor.cc
index 7facb7b..c5fe78fc 100644
--- a/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/content/browser/indexed_db/indexed_db_cursor.cc
@@ -161,9 +161,13 @@
     mojo_value = blink::mojom::IDBValue::New();
   }
 
+  std::vector<IndexedDBKey> keys = {key()};
+  std::vector<IndexedDBKey> primary_keys = {primary_key()};
+  std::vector<blink::mojom::IDBValuePtr> values;
+  values.push_back(std::move(mojo_value));
   blink::mojom::IDBCursorValuePtr cursor_value =
-      blink::mojom::IDBCursorValue::New(key(), primary_key(),
-                                        std::move(mojo_value));
+      blink::mojom::IDBCursorValue::New(
+          std::move(keys), std::move(primary_keys), std::move(values));
   std::move(callback).Run(blink::mojom::IDBErrorPtr(), std::move(cursor_value));
   return s;
 }
@@ -243,35 +247,50 @@
     mojo_value = blink::mojom::IDBValue::New();
   }
 
+  std::vector<IndexedDBKey> keys = {this->key()};
+  std::vector<IndexedDBKey> primary_keys = {this->primary_key()};
+  std::vector<blink::mojom::IDBValuePtr> values;
+  values.push_back(std::move(mojo_value));
   blink::mojom::IDBCursorValuePtr cursor_value =
-      blink::mojom::IDBCursorValue::New(this->key(), this->primary_key(),
-                                        std::move(mojo_value));
+      blink::mojom::IDBCursorValue::New(
+          std::move(keys), std::move(primary_keys), std::move(values));
   std::move(callback).Run(blink::mojom::IDBErrorPtr(), std::move(cursor_value));
   return s;
 }
 
 void IndexedDBCursor::PrefetchContinue(
+    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
     int number_to_fetch,
-    scoped_refptr<IndexedDBCallbacks> callbacks) {
+    blink::mojom::IDBCursor::PrefetchCallback callback) {
   IDB_TRACE("IndexedDBCursor::PrefetchContinue");
 
   if (closed_) {
-    callbacks->OnError(CreateCursorClosedError());
+    const IndexedDBDatabaseError error(CreateCursorClosedError());
+    std::move(callback).Run(
+        blink::mojom::IDBError::New(error.code(), error.message()),
+        blink::mojom::IDBCursorValuePtr());
     return;
   }
 
   transaction_->ScheduleTask(
       task_type_,
-      BindWeakOperation(&IndexedDBCursor::CursorPrefetchIterationOperation,
-                        ptr_factory_.GetWeakPtr(), number_to_fetch, callbacks));
+      BindWeakOperation(
+          &IndexedDBCursor::CursorPrefetchIterationOperation,
+          ptr_factory_.GetWeakPtr(), std::move(dispatcher_host),
+          base::WrapRefCounted(dispatcher_host->context()->TaskRunner()),
+          number_to_fetch, std::move(callback)));
 }
 
 leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
+    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+    scoped_refptr<base::SequencedTaskRunner> idb_runner,
     int number_to_fetch,
-    scoped_refptr<IndexedDBCallbacks> callbacks,
+    blink::mojom::IDBCursor::PrefetchCallback callback,
     IndexedDBTransaction* /*transaction*/) {
   IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
   leveldb::Status s = leveldb::Status::OK();
+  if (!dispatcher_host)
+    return s;
 
   std::vector<IndexedDBKey> found_keys;
   std::vector<IndexedDBKey> found_primary_keys;
@@ -292,11 +311,15 @@
         // We've reached the end, so just return what we have.
         break;
       }
+      // |transaction_| must be valid for CreateError(), so we can't call
+      // Close() until after calling CreateError().
       IndexedDBDatabaseError error =
           CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
                       "Error continuing cursor.", transaction_);
       Close();
-      callbacks->OnError(std::move(error));
+      std::move(callback).Run(
+          blink::mojom::IDBError::New(error.code(), error.message()),
+          blink::mojom::IDBCursorValuePtr());
       return s;
     }
 
@@ -331,12 +354,38 @@
   }
 
   if (found_keys.empty()) {
-    callbacks->OnSuccess(nullptr);
+    std::move(callback).Run(blink::mojom::IDBErrorPtr(),
+                            blink::mojom::IDBCursorValuePtr());
     return s;
   }
 
-  callbacks->OnSuccessWithPrefetch(
-      found_keys, found_primary_keys, &found_values);
+  DCHECK_EQ(found_keys.size(), found_primary_keys.size());
+  DCHECK_EQ(found_keys.size(), found_values.size());
+
+  std::vector<blink::mojom::IDBValuePtr> mojo_values;
+  mojo_values.reserve(found_values.size());
+  for (size_t i = 0; i < found_values.size(); ++i)
+    mojo_values.push_back(
+        IndexedDBValue::ConvertAndEraseValue(&found_values[i]));
+
+  std::vector<IndexedDBCallbacks::IndexedDBValueBlob> value_blobs;
+  for (size_t i = 0; i < mojo_values.size(); ++i) {
+    IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
+        &value_blobs, found_values[i].blob_info,
+        &mojo_values[i]->blob_or_file_info);
+  }
+
+  if (!IndexedDBCallbacks::CreateAllBlobs(
+          dispatcher_host->blob_storage_context(), idb_runner,
+          std::move(value_blobs))) {
+    return s;
+  }
+
+  blink::mojom::IDBCursorValuePtr cursor_value =
+      blink::mojom::IDBCursorValue::New(std::move(found_keys),
+                                        std::move(found_primary_keys),
+                                        std::move(mojo_values));
+  std::move(callback).Run(blink::mojom::IDBErrorPtr(), std::move(cursor_value));
   return s;
 }
 
diff --git a/content/browser/indexed_db/indexed_db_cursor.h b/content/browser/indexed_db/indexed_db_cursor.h
index 5021ae8..e3d935a2 100644
--- a/content/browser/indexed_db/indexed_db_cursor.h
+++ b/content/browser/indexed_db/indexed_db_cursor.h
@@ -36,8 +36,9 @@
                 std::unique_ptr<blink::IndexedDBKey> key,
                 std::unique_ptr<blink::IndexedDBKey> primary_key,
                 blink::mojom::IDBCursor::CursorContinueCallback callback);
-  void PrefetchContinue(int number_to_fetch,
-                        scoped_refptr<IndexedDBCallbacks> callbacks);
+  void PrefetchContinue(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+                        int number_to_fetch,
+                        blink::mojom::IDBCursor::PrefetchCallback callback);
   leveldb::Status PrefetchReset(int used_prefetches, int unused_prefetches);
 
   void OnRemoveBinding(base::OnceClosure remove_binding_cb);
@@ -70,8 +71,10 @@
       blink::mojom::IDBCursor::AdvanceCallback callback,
       IndexedDBTransaction* transaction);
   leveldb::Status CursorPrefetchIterationOperation(
+      base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
+      scoped_refptr<base::SequencedTaskRunner> idb_runner,
       int number_to_fetch,
-      scoped_refptr<IndexedDBCallbacks> callbacks,
+      blink::mojom::IDBCursor::PrefetchCallback callback,
       IndexedDBTransaction* transaction);
 
  private:
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 068a7c8..1411491 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -1027,14 +1027,6 @@
     url_loader_removed_headers_ = removed_headers;
     url_loader_modified_headers_ = modified_headers;
 
-    // Don't send Accept: application/signed-exchange for fallback redirects.
-    if (redirect_info_.is_signed_exchange_fallback_redirect) {
-      url_loader_modified_headers_.SetHeader(network::kAcceptHeader,
-                                             network::kFrameAcceptHeader);
-      resource_request_->headers.SetHeader(network::kAcceptHeader,
-                                           network::kFrameAcceptHeader);
-    }
-
     Restart();
   }
 
diff --git a/content/browser/renderer_host/input/fling_controller.cc b/content/browser/renderer_host/input/fling_controller.cc
index 92445d3..0ec5116 100644
--- a/content/browser/renderer_host/input/fling_controller.cc
+++ b/content/browser/renderer_host/input/fling_controller.cc
@@ -148,9 +148,40 @@
 
 bool FlingController::FilterGestureEvent(
     const GestureEventWithLatencyInfo& gesture_event) {
-  return !ShouldForwardForGFCFiltering(gesture_event) ||
-         !ShouldForwardForTapSuppression(gesture_event) ||
-         FilterGestureEventForFlingBoosting(gesture_event);
+  if (!ShouldForwardForGFCFiltering(gesture_event) ||
+      !ShouldForwardForTapSuppression(gesture_event) ||
+      FilterGestureEventForFlingBoosting(gesture_event))
+    return true;
+
+  if (gesture_event.event.GetType() == WebInputEvent::kGestureScrollUpdate) {
+    last_seen_scroll_update_ = gesture_event.event.TimeStamp();
+  } else if (gesture_event.event.GetType() ==
+                 WebInputEvent::kGestureScrollEnd ||
+             gesture_event.event.GetType() ==
+                 WebInputEvent::kGestureScrollBegin) {
+    // TODO(bokan): We reset this on Begin as well as End since there appear to
+    // be cases where we see an invalid event sequence:
+    // https://crbug.com/928569.
+    last_seen_scroll_update_ = base::TimeTicks();
+  }
+
+  // fling_controller_ is in charge of handling GFS events and the events are
+  // not sent to the renderer, the controller processes the fling and generates
+  // fling progress events (wheel events for touchpad and GSU events for
+  // touchscreen and autoscroll) which are handled normally.
+  if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) {
+    ProcessGestureFlingStart(gesture_event);
+    return true;
+  }
+
+  // If the GestureFlingStart event is processed by the fling_controller_, the
+  // GestureFlingCancel event should be the same.
+  if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingCancel) {
+    ProcessGestureFlingCancel(gesture_event);
+    return true;
+  }
+
+  return false;
 }
 
 void FlingController::ProcessGestureFlingStart(
@@ -216,7 +247,7 @@
     // later than the fling start time, delay the fling start time to one frame
     // prior to the current time. This makes sure that at least one progress
     // event is sent while the fling is active even when the fling duration is
-    // short (samll velocity) and the time delta between its timestamp and its
+    // short (small velocity) and the time delta between its timestamp and its
     // processing time is big (e.g. When a GFS gets bubbled from an oopif).
     if (current_time >= current_fling_parameters_.start_time +
                             kMaxMicrosecondsFromFlingTimestampToFirstProgress) {
@@ -419,8 +450,16 @@
   current_fling_parameters_.global_point = fling_start_event.PositionInScreen();
   current_fling_parameters_.modifiers = fling_start_event.GetModifiers();
   current_fling_parameters_.source_device = fling_start_event.SourceDevice();
-  // NOTE: This time may be more than a frame in the past.
-  current_fling_parameters_.start_time = fling_start_event.TimeStamp();
+
+  if (fling_start_event.SourceDevice() ==
+          blink::kWebGestureDeviceSyntheticAutoscroll ||
+      last_seen_scroll_update_.is_null()) {
+    current_fling_parameters_.start_time = fling_start_event.TimeStamp();
+  } else {
+    // To maintain a smooth, continuous transition from a drag scroll to a fling
+    // scroll, the animation should begin at the time of the last update.
+    current_fling_parameters_.start_time = last_seen_scroll_update_;
+  }
 
   if (velocity.IsZero() && fling_start_event.SourceDevice() !=
                                blink::kWebGestureDeviceSyntheticAutoscroll) {
diff --git a/content/browser/renderer_host/input/fling_controller.h b/content/browser/renderer_host/input/fling_controller.h
index 4bd1d1b..4254134b 100644
--- a/content/browser/renderer_host/input/fling_controller.h
+++ b/content/browser/renderer_host/input/fling_controller.h
@@ -178,6 +178,10 @@
   // The clock used; overridable for tests.
   const base::TickClock* clock_;
 
+  // Time of the last seen scroll update that wasn't filtered. Used to know the
+  // starting time for a possible fling gesture curve.
+  base::TimeTicks last_seen_scroll_update_;
+
   base::WeakPtrFactory<FlingController> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FlingController);
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc
index f52f544..502026f 100644
--- a/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -97,8 +97,26 @@
       // Wait for up to one frame before processing the event.
       AdvanceTime(base::RandInt(0, static_cast<int>(kFrameDelta)));
     }
-    if (!fling_controller_->FilterGestureEvent(fling_start_with_latency))
-      fling_controller_->ProcessGestureFlingStart(fling_start_with_latency);
+    fling_controller_->FilterGestureEvent(fling_start_with_latency);
+  }
+
+  void SimulateScrollUpdate(blink::WebGestureDevice source_device,
+                            const gfx::Vector2dF& delta) {
+    WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
+                                  NowTicks(), source_device);
+    scroll_update.data.scroll_update.delta_x = delta.x();
+    scroll_update.data.scroll_update.delta_y = delta.y();
+    scroll_update.data.scroll_update.velocity_x = delta.x();
+    scroll_update.data.scroll_update.velocity_y = delta.y();
+    scroll_update.data.scroll_update.inertial_phase =
+        WebGestureEvent::kNonMomentumPhase;
+    scroll_update.data.scroll_update.previous_update_in_sequence_prevented =
+        false;
+    scroll_update.data.scroll_update.delta_units =
+        WebGestureEvent::kPrecisePixels;
+    GestureEventWithLatencyInfo scroll_update_with_latency(scroll_update);
+
+    fling_controller_->FilterGestureEvent(scroll_update_with_latency);
   }
 
   void SimulateFlingCancel(blink::WebGestureDevice source_device) {
@@ -109,10 +127,7 @@
     if (source_device == blink::kWebGestureDeviceSyntheticAutoscroll)
       fling_cancel.data.fling_cancel.prevent_boosting = true;
     GestureEventWithLatencyInfo fling_cancel_with_latency(fling_cancel);
-    last_fling_cancel_filtered_ =
-        fling_controller_->FilterGestureEvent(fling_cancel_with_latency);
-    if (!last_fling_cancel_filtered_)
-      fling_controller_->ProcessGestureFlingCancel(fling_cancel_with_latency);
+    fling_controller_->FilterGestureEvent(fling_cancel_with_latency);
   }
 
   void ProgressFling(base::TimeTicks current_time) {
@@ -135,7 +150,6 @@
   int wheel_event_count_ = 0;
   WebMouseWheelEvent last_sent_wheel_;
   WebGestureEvent last_sent_gesture_;
-  bool last_fling_cancel_filtered_ = false;
   bool scheduled_next_fling_progress_ = false;
   bool notified_client_after_fling_stop_ = false;
   bool first_wheel_event_sent_ = false;
@@ -173,7 +187,7 @@
 TEST_P(FlingControllerTest, ControllerHandlesTouchpadGestureFling) {
   SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
-  // Processing GFS will send the first fling prgoress event if the time delta
+  // Processing GFS will send the first fling progress event if the time delta
   // between the timestamp of the GFS and the time that ProcessGestureFlingStart
   // is called is large enough.
   bool process_GFS_sent_first_event = first_wheel_event_sent_;
@@ -197,7 +211,6 @@
 
   // Now cancel the fling. The GFC will get suppressed by fling booster.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchpad);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
   EXPECT_TRUE(FlingInProgress());
 
   // Wait for the boosting timer to expire. The delayed cancelation must work.
@@ -209,6 +222,30 @@
   EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
 }
 
+// Ensure that the start time of a fling is measured from the last received
+// GSU. This ensures that the first progress fling during FlingStart should
+// send significant delta. If we're using the FlingStart as the start time, we
+// would send none or very little delta.
+TEST_P(FlingControllerTest, FlingStartsAtLastScrollUpdate) {
+  SimulateScrollUpdate(blink::kWebGestureDeviceTouchscreen,
+                       gfx::Vector2dF(1000, 0));
+  double time_to_advance_ms = 30.0;
+  AdvanceTime(time_to_advance_ms);
+  SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
+                     gfx::Vector2dF(1000, 0), /*wait_before_processing=*/false);
+  EXPECT_TRUE(FlingInProgress());
+
+  if (NeedsBeginFrameForFlingProgress())
+    ProgressFling(NowTicks());
+
+  // We haven't advanced time since the FlingStart. Ensure we still send a
+  // significant amount of delta (~0.030sec * 1000pixels/sec) since we should
+  // be measuring the time since the last GSU.
+  EXPECT_EQ(1, sent_scroll_gesture_count_);
+  ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
+  EXPECT_NEAR(last_sent_gesture_.data.scroll_update.delta_x, 30.0, 5);
+}
+
 TEST_P(FlingControllerTest, ControllerHandlesTouchscreenGestureFling) {
   SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
                      gfx::Vector2dF(1000, 0));
@@ -224,7 +261,6 @@
 
   // Now cancel the fling. The GFC will get suppressed by fling booster.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
   EXPECT_TRUE(FlingInProgress());
 
   // Wait for the boosting timer to expire. The delayed cancelation must work.
@@ -237,7 +273,7 @@
 TEST_P(FlingControllerTest, ControllerSendsWheelEndWhenTouchpadFlingIsOver) {
   SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(100, 0));
   EXPECT_TRUE(FlingInProgress());
-  // Processing GFS will send the first fling prgoress event if the time delta
+  // Processing GFS will send the first fling progress event if the time delta
   // between the timestamp of the GFS and the time that ProcessGestureFlingStart
   // is called is large enough.
   bool process_GFS_sent_first_event = first_wheel_event_sent_;
@@ -290,7 +326,7 @@
 TEST_P(FlingControllerTest, EarlyTouchpadFlingCancelationOnFlingStop) {
   SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
-  // Processing GFS will send the first fling prgoress event if the time delta
+  // Processing GFS will send the first fling progress event if the time delta
   // between the timestamp of the GFS and the time that ProcessGestureFlingStart
   // is called is large enough.
   bool process_GFS_sent_first_event = first_wheel_event_sent_;
@@ -333,19 +369,18 @@
 TEST_P(FlingControllerTest, GestureFlingCancelsFiltered) {
   // GFC without previous GFS is dropped.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
+  EXPECT_FALSE(FlingInProgress());
 
   // GFC after previous GFS is filtered by fling booster.
   SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
                      gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
   SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
   EXPECT_TRUE(FlingInProgress());
 
   // Any other GFC while the fling cancelation is deferred gets filtered.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
+  EXPECT_TRUE(FlingInProgress());
 }
 
 TEST_P(FlingControllerTest, GestureFlingNotCancelledBySmallTimeDelta) {
@@ -416,7 +451,6 @@
 
   // Start the fling animation later, as if there was a delay in event dispatch.
   AdvanceTime(1.f);
-  ASSERT_FALSE(fling_controller_->FilterGestureEvent(fling_start_with_latency));
   fling_controller_->ProcessGestureFlingStart(fling_start_with_latency);
   EXPECT_TRUE(FlingInProgress());
 
@@ -450,7 +484,7 @@
 TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
   SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
-  // Processing GFS will send the first fling prgoress event if the time delta
+  // Processing GFS will send the first fling progress event if the time delta
   // between the timestamp of the GFS and the time that ProcessGestureFlingStart
   // is called is large enough.
   bool process_GFS_sent_first_event = first_wheel_event_sent_;
@@ -473,7 +507,6 @@
 
   // Now cancel the fling. The GFC will get suppressed by fling booster.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchpad);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
   EXPECT_TRUE(FlingInProgress());
 
   // The second GFS will boost the current active fling.
@@ -496,7 +529,6 @@
 
   // Now cancel the fling. The GFC will get suppressed by fling booster.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
   EXPECT_TRUE(FlingInProgress());
 
   // The second GFS will boost the current active fling.
@@ -513,7 +545,6 @@
 
   // Now cancel the fling. The GFC will get suppressed by fling booster.
   SimulateFlingCancel(blink::kWebGestureDeviceTouchscreen);
-  EXPECT_TRUE(last_fling_cancel_filtered_);
   EXPECT_TRUE(FlingInProgress());
 
   // Wait for the boosting timer to expire. The delayed cancelation must work
@@ -548,7 +579,6 @@
   // Now cancel the fling. The GFC won't get suppressed by fling booster since
   // autoscroll fling doesn't have boosting.
   SimulateFlingCancel(blink::kWebGestureDeviceSyntheticAutoscroll);
-  EXPECT_FALSE(last_fling_cancel_filtered_);
   EXPECT_FALSE(FlingInProgress());
 }
 
diff --git a/content/browser/renderer_host/input/fling_scheduler_unittest.cc b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
index 392cc8d..1a13b4f 100644
--- a/content/browser/renderer_host/input/fling_scheduler_unittest.cc
+++ b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
@@ -86,8 +86,7 @@
     fling_start.data.fling_start.velocity_x = velocity.x();
     fling_start.data.fling_start.velocity_y = velocity.y();
     GestureEventWithLatencyInfo fling_start_with_latency(fling_start);
-    if (!fling_controller_->FilterGestureEvent(fling_start_with_latency))
-      fling_controller_->ProcessGestureFlingStart(fling_start_with_latency);
+    fling_controller_->FilterGestureEvent(fling_start_with_latency);
   }
 
   void SimulateFlingCancel() {
@@ -96,8 +95,7 @@
         blink::kWebGestureDeviceTouchscreen);
     fling_cancel.data.fling_cancel.prevent_boosting = true;
     GestureEventWithLatencyInfo fling_cancel_with_latency(fling_cancel);
-    if (!fling_controller_->FilterGestureEvent(fling_cancel_with_latency))
-      fling_controller_->ProcessGestureFlingCancel(fling_cancel_with_latency);
+    fling_controller_->FilterGestureEvent(fling_cancel_with_latency);
   }
 
   // FlingControllerEventSenderClient
diff --git a/content/browser/renderer_host/input/gesture_event_queue.cc b/content/browser/renderer_host/input/gesture_event_queue.cc
index 6724bfb..e9d5dc6 100644
--- a/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -57,26 +57,7 @@
 bool GestureEventQueue::FlingControllerFilterEvent(
     const GestureEventWithLatencyInfo& gesture_event) {
   TRACE_EVENT0("input", "GestureEventQueue::QueueEvent");
-  if (fling_controller_.FilterGestureEvent(gesture_event))
-    return true;
-
-  // fling_controller_ is in charge of handling GFS events and the events are
-  // not sent to the renderer, the controller processes the fling and generates
-  // fling progress events (wheel events for touchpad and GSU events for
-  // touchscreen and autoscroll) which are handled normally.
-  if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) {
-    fling_controller_.ProcessGestureFlingStart(gesture_event);
-    return true;
-  }
-
-  // If the GestureFlingStart event is processed by the fling_controller_, the
-  // GestureFlingCancel event should be the same.
-  if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingCancel) {
-    fling_controller_.ProcessGestureFlingCancel(gesture_event);
-    return true;
-  }
-
-  return false;
+  return fling_controller_.FilterGestureEvent(gesture_event);
 }
 
 void GestureEventQueue::QueueDeferredEvents(
diff --git a/content/browser/service_worker/service_worker_context_request_handler.cc b/content/browser/service_worker/service_worker_context_request_handler.cc
deleted file mode 100644
index 32af334..0000000
--- a/content/browser/service_worker/service_worker_context_request_handler.cc
+++ /dev/null
@@ -1,209 +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.
-
-#include "content/browser/service_worker/service_worker_context_request_handler.h"
-
-#include "base/command_line.h"
-#include "base/time/time.h"
-#include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_provider_host.h"
-#include "content/browser/service_worker/service_worker_read_from_cache_job.h"
-#include "content/browser/service_worker/service_worker_storage.h"
-#include "content/browser/service_worker/service_worker_version.h"
-#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
-#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/common/content_switches.h"
-#include "net/base/load_flags.h"
-#include "net/log/net_log.h"
-#include "net/log/net_log_event_type.h"
-#include "net/log/net_log_with_source.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_error_job.h"
-#include "services/network/public/cpp/resource_response_info.h"
-
-namespace content {
-
-ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
-    base::WeakPtr<ServiceWorkerContextCore> context,
-    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
-    base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
-    ResourceType resource_type)
-    : ServiceWorkerRequestHandler(context,
-                                  provider_host,
-                                  blob_storage_context,
-                                  resource_type),
-      version_(provider_host_->running_hosted_version()) {
-  DCHECK(provider_host_->IsProviderForServiceWorker());
-  DCHECK(version_);
-}
-
-ServiceWorkerContextRequestHandler::~ServiceWorkerContextRequestHandler() {
-}
-
-// static
-std::string ServiceWorkerContextRequestHandler::CreateJobStatusToString(
-    CreateJobStatus status) {
-  switch (status) {
-    case CreateJobStatus::UNINITIALIZED:
-      return "UNINITIALIZED";
-    case CreateJobStatus::WRITE_JOB:
-      return "WRITE_JOB";
-    case CreateJobStatus::WRITE_JOB_WITH_INCUMBENT:
-      return "WRITE_JOB_WITH_INCUMBENT";
-    case CreateJobStatus::READ_JOB:
-      return "READ_JOB";
-    case CreateJobStatus::READ_JOB_FOR_DUPLICATE_SCRIPT_IMPORT:
-      return "READ_JOB_FOR_DUPLICATE_SCRIPT_IMPORT";
-    case CreateJobStatus::ERROR_NO_PROVIDER:
-      return "ERROR_NO_PROVIDER";
-    case CreateJobStatus::ERROR_REDUNDANT_VERSION:
-      return "ERROR_REDUNDANT_VERSION";
-    case CreateJobStatus::ERROR_NO_CONTEXT:
-      return "ERROR_NO_CONTEXT";
-    case CreateJobStatus::ERROR_REDIRECT:
-      return "ERROR_REDIRECT";
-    case CreateJobStatus::ERROR_UNINSTALLED_SCRIPT_IMPORT:
-      return "ERROR_UNINSTALLED_SCRIPT_IMPORT";
-    case CreateJobStatus::ERROR_OUT_OF_RESOURCE_IDS:
-      return "ERROR_OUT_OF_RESOURCE_IDS";
-  }
-  NOTREACHED() << static_cast<int>(status);
-  return "UNKNOWN";
-}
-
-net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
-    net::URLRequest* request,
-    net::NetworkDelegate* network_delegate,
-    ResourceContext* resource_context) {
-  // We only use the script cache for main script loading and
-  // importScripts(), even if a cached script is xhr'd, we don't
-  // retrieve it from the script cache.
-  // TODO(falken): Get the desired behavior clarified in the spec,
-  // and make tweak the behavior here to match.
-  if (resource_type_ != RESOURCE_TYPE_SERVICE_WORKER &&
-      resource_type_ != RESOURCE_TYPE_SCRIPT) {
-    // Fall back to network.
-    return nullptr;
-  }
-
-  CreateJobStatus status = CreateJobStatus::UNINITIALIZED;
-  net::URLRequestJob* job =
-      MaybeCreateJobImpl(request, network_delegate, &status);
-  const bool is_main_script = resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
-  ServiceWorkerMetrics::RecordContextRequestHandlerStatus(
-      status, ServiceWorkerVersion::IsInstalled(version_->status()),
-      is_main_script);
-  if (job)
-    return job;
-
-  // If we got here, a job couldn't be created. Return an error job rather than
-  // falling back to network. Otherwise the renderer may receive the response
-  // from network and start a service worker whose browser-side
-  // ServiceWorkerVersion is not properly initialized.
-  std::string error_str(CreateJobStatusToString(status));
-  request->net_log().AddEvent(
-      net::NetLogEventType::SERVICE_WORKER_SCRIPT_LOAD_UNHANDLED_REQUEST_ERROR,
-      net::NetLog::StringCallback("error", &error_str));
-
-  return new net::URLRequestErrorJob(request, network_delegate,
-                                     net::Error::ERR_FAILED);
-}
-
-net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
-    net::URLRequest* request,
-    net::NetworkDelegate* network_delegate,
-    CreateJobStatus* out_status) {
-  if (!context_) {
-    *out_status = CreateJobStatus::ERROR_NO_CONTEXT;
-    return nullptr;
-  }
-  if (!provider_host_) {
-    *out_status = CreateJobStatus::ERROR_NO_PROVIDER;
-    return nullptr;
-  }
-
-  // This could happen if browser-side has set the status to redundant but the
-  // worker has not yet stopped. The worker is already doomed so just reject the
-  // request. Handle it specially here because otherwise it'd be unclear whether
-  // "REDUNDANT" should count as installed or not installed when making
-  // decisions about how to handle the request and logging UMA.
-  if (version_->status() == ServiceWorkerVersion::REDUNDANT) {
-    *out_status = CreateJobStatus::ERROR_REDUNDANT_VERSION;
-    return nullptr;
-  }
-
-  // We currently have no use case for hijacking a redirected request.
-  if (request->url_chain().size() > 1) {
-    *out_status = CreateJobStatus::ERROR_REDIRECT;
-    return nullptr;
-  }
-
-  const bool is_main_script = resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
-  int64_t resource_id =
-      version_->script_cache_map()->LookupResourceId(request->url());
-  if (resource_id != kInvalidServiceWorkerResourceId) {
-    if (ServiceWorkerVersion::IsInstalled(version_->status())) {
-      // An installed worker is loading a stored script.
-      *out_status = CreateJobStatus::READ_JOB;
-    } else {
-      // A new worker is loading a stored script. The script was already
-      // imported (or the main script is being recursively imported).
-      *out_status = CreateJobStatus::READ_JOB_FOR_DUPLICATE_SCRIPT_IMPORT;
-    }
-    return new ServiceWorkerReadFromCacheJob(request, network_delegate,
-                                             resource_type_, context_, version_,
-                                             resource_id);
-  }
-
-  // An installed worker is importing a non-stored script.
-  if (ServiceWorkerVersion::IsInstalled(version_->status())) {
-    DCHECK(!is_main_script);
-    *out_status = CreateJobStatus::ERROR_UNINSTALLED_SCRIPT_IMPORT;
-    return nullptr;
-  }
-
-  // A new worker is loading a script for the first time. Create a write job to
-  // store the script.
-  ServiceWorkerRegistration* registration =
-      context_->GetLiveRegistration(version_->registration_id());
-  DCHECK(registration);  // We're registering or updating so must be there.
-
-  resource_id = context_->storage()->NewResourceId();
-  if (resource_id == kInvalidServiceWorkerResourceId) {
-    *out_status = CreateJobStatus::ERROR_OUT_OF_RESOURCE_IDS;
-    return nullptr;
-  }
-
-  // Bypass the browser cache for initial installs and update checks after 24
-  // hours have passed.
-  int extra_load_flags = 0;
-  base::TimeDelta time_since_last_check =
-      base::Time::Now() - registration->last_update_check();
-
-  if (ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
-          is_main_script, registration->update_via_cache()) ||
-      time_since_last_check > kServiceWorkerScriptMaxCacheAge ||
-      version_->force_bypass_cache_for_scripts()) {
-    extra_load_flags = net::LOAD_BYPASS_CACHE;
-  }
-
-  ServiceWorkerVersion* stored_version = registration->waiting_version()
-                                             ? registration->waiting_version()
-                                             : registration->active_version();
-  int64_t incumbent_resource_id = kInvalidServiceWorkerResourceId;
-  if (is_main_script) {
-    if (stored_version && stored_version->script_url() == request->url()) {
-      incumbent_resource_id =
-          stored_version->script_cache_map()->LookupResourceId(request->url());
-    }
-  }
-  *out_status = incumbent_resource_id == kInvalidServiceWorkerResourceId
-                    ? CreateJobStatus::WRITE_JOB
-                    : CreateJobStatus::WRITE_JOB_WITH_INCUMBENT;
-  return new ServiceWorkerWriteToCacheJob(
-      request, network_delegate, resource_type_, context_, version_.get(),
-      extra_load_flags, resource_id, incumbent_resource_id);
-}
-
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_request_handler.h b/content/browser/service_worker/service_worker_context_request_handler.h
deleted file mode 100644
index 4c9fa5c..0000000
--- a/content/browser/service_worker/service_worker_context_request_handler.h
+++ /dev/null
@@ -1,84 +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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_REQUEST_HANDLER_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_REQUEST_HANDLER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "content/browser/service_worker/service_worker_request_handler.h"
-
-namespace content {
-
-class ServiceWorkerVersion;
-
-// A request handler derivative used to handle requests from
-// service workers.
-class CONTENT_EXPORT ServiceWorkerContextRequestHandler
-    : public ServiceWorkerRequestHandler {
- public:
-  // The result status for MaybeCreateJob. Used in histograms. Append-only.
-  enum class CreateJobStatus {
-    // Unitialized status.
-    UNINITIALIZED,
-    // A ServiceWorkerWriteToCacheJob was created.
-    WRITE_JOB,
-    // A ServiceWorkerWriteToCacheJob was created with an incumbent script to
-    // compare against.
-    WRITE_JOB_WITH_INCUMBENT,
-    // A ServiceWorkerReadFromCacheJob was created.
-    READ_JOB,
-    // A ServiceWorkerReadFromCacheJob was created for a new worker that is
-    // importing a script that was already imported.
-    READ_JOB_FOR_DUPLICATE_SCRIPT_IMPORT,
-    // A job could not be created because there is no live
-    // ServiceWorkerProviderHost.
-    ERROR_NO_PROVIDER,
-    // A job could not be created because the ServiceWorkerVersion is in status
-    // REDUNDANT.
-    ERROR_REDUNDANT_VERSION,
-    // A job could not be created because there is no live
-    // ServiceWorkerContextCore.
-    ERROR_NO_CONTEXT,
-    // A job could not be created because a redirect occurred.
-    ERROR_REDIRECT,
-    // A job was not created because an installed worker is importing a script
-    // that was not stored at installation time.
-    ERROR_UNINSTALLED_SCRIPT_IMPORT,
-    // A job could not be created because there are no resource ids available.
-    ERROR_OUT_OF_RESOURCE_IDS,
-    // Add new types here.
-
-    kMaxValue = ERROR_OUT_OF_RESOURCE_IDS,
-  };
-
-  ServiceWorkerContextRequestHandler(
-      base::WeakPtr<ServiceWorkerContextCore> context,
-      base::WeakPtr<ServiceWorkerProviderHost> provider_host,
-      base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
-      ResourceType resource_type);
-  ~ServiceWorkerContextRequestHandler() override;
-
-  // Called via custom URLRequestJobFactory.
-  net::URLRequestJob* MaybeCreateJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate,
-      ResourceContext* resource_context) override;
-
-  static std::string CreateJobStatusToString(CreateJobStatus status);
-
- private:
-  net::URLRequestJob* MaybeCreateJobImpl(net::URLRequest* request,
-                                         net::NetworkDelegate* network_delegate,
-                                         CreateJobStatus* out_status);
-
-  scoped_refptr<ServiceWorkerVersion> version_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextRequestHandler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_REQUEST_HANDLER_H_
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
index a5745ab0..cbf37a3d 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -16,6 +16,7 @@
 #include "base/time/time.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/common/resource_type.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
@@ -31,6 +32,7 @@
 
 namespace content {
 
+class ServiceWorkerContextWrapper;
 class ServiceWorkerVersion;
 class URLLoaderFactoryGetter;
 
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc
index 255678d..386d74f 100644
--- a/content/browser/service_worker/service_worker_metrics.cc
+++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -842,36 +842,6 @@
   }
 }
 
-void ServiceWorkerMetrics::RecordContextRequestHandlerStatus(
-    ServiceWorkerContextRequestHandler::CreateJobStatus status,
-    bool is_installed,
-    bool is_main_script) {
-  if (is_installed) {
-    if (is_main_script) {
-      UMA_HISTOGRAM_ENUMERATION(
-          "ServiceWorker.ContextRequestHandlerStatus.InstalledWorker."
-          "MainScript",
-          status);
-    } else {
-      UMA_HISTOGRAM_ENUMERATION(
-          "ServiceWorker.ContextRequestHandlerStatus.InstalledWorker."
-          "ImportedScript",
-          status);
-    }
-  } else {
-    if (is_main_script) {
-      UMA_HISTOGRAM_ENUMERATION(
-          "ServiceWorker.ContextRequestHandlerStatus.NewWorker.MainScript",
-          status);
-    } else {
-      UMA_HISTOGRAM_ENUMERATION(
-          "ServiceWorker.ContextRequestHandlerStatus.NewWorker."
-          "ImportedScript",
-          status);
-    }
-  }
-}
-
 void ServiceWorkerMetrics::RecordRuntime(base::TimeDelta time) {
   // Start at 1 second since we expect service worker to last at least this
   // long: the update timer and idle timeout timer run on the order of seconds.
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h
index 4112e80..f76a462 100644
--- a/content/browser/service_worker/service_worker_metrics.h
+++ b/content/browser/service_worker/service_worker_metrics.h
@@ -11,11 +11,11 @@
 
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "content/browser/service_worker/service_worker_context_request_handler.h"
 #include "content/browser/service_worker/service_worker_database.h"
 #include "content/browser/service_worker/service_worker_installed_script_reader.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/browser/service_worker_context.h"
+#include "content/public/common/resource_type.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/embedded_worker.mojom.h"
 #include "ui/base/page_transition_types.h"
@@ -418,13 +418,6 @@
       StartSituation start_situation,
       ResourceType resource_type);
 
-  // Records the result of trying to handle a request for a service worker
-  // script.
-  static void RecordContextRequestHandlerStatus(
-      ServiceWorkerContextRequestHandler::CreateJobStatus status,
-      bool is_installed,
-      bool is_main_script);
-
   static void RecordRuntime(base::TimeDelta time);
 
   // Records the result of starting service worker for a navigation hint.
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index a513911..379830f5 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -20,7 +20,6 @@
 #include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_consts.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_context_request_handler.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_controllee_request_handler.h"
 #include "content/browser/service_worker/service_worker_registration_object_host.h"
@@ -641,34 +640,27 @@
     base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
     scoped_refptr<network::ResourceRequestBody> body,
     bool skip_service_worker) {
-  // |skip_service_worker| is meant to apply to requests that could be handled
-  // by a service worker, as opposed to requests for the service worker script
-  // itself. So ignore it here for the service worker script and its imported
-  // scripts.
-  // TODO(falken): Really it should be treated as an error to set
-  // |skip_service_worker| for requests to start the service worker, but it's
-  // difficult to fix that renderer-side (maybe try after S13nServiceWorker).
-  if (IsProviderForServiceWorker() &&
-      (resource_type == RESOURCE_TYPE_SERVICE_WORKER ||
-       resource_type == RESOURCE_TYPE_SCRIPT)) {
-    skip_service_worker = false;
-  }
+  // We only get here for main resource requests for service worker clients
+  // (navigations, dedicated workers, and shared workers).
+  DCHECK(!IsProviderForServiceWorker());
+
+  // TODO(falken): Add DCHECK(IsMainResourceType()) and remove the calls to it
+  // below.
+
   if (skip_service_worker) {
     if (!ServiceWorkerUtils::IsMainResourceType(resource_type))
       return std::unique_ptr<ServiceWorkerRequestHandler>();
     return std::make_unique<ServiceWorkerURLTrackingRequestHandler>(
         context_, AsWeakPtr(), blob_storage_context, resource_type);
   }
-  if (IsProviderForServiceWorker()) {
-    return std::make_unique<ServiceWorkerContextRequestHandler>(
-        context_, AsWeakPtr(), blob_storage_context, resource_type);
-  }
+
   if (ServiceWorkerUtils::IsMainResourceType(resource_type) || controller()) {
     return std::make_unique<ServiceWorkerControlleeRequestHandler>(
         context_, AsWeakPtr(), blob_storage_context, request_mode,
         credentials_mode, redirect_mode, integrity, keepalive, resource_type,
         request_context_type, frame_type, body);
   }
+
   return std::unique_ptr<ServiceWorkerRequestHandler>();
 }
 
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 23b35f86..258fcbc 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -472,7 +472,6 @@
   friend class LinkHeaderServiceWorkerTest;
   friend class ServiceWorkerProviderHostTest;
   friend class ServiceWorkerWriteToCacheJobTest;
-  friend class ServiceWorkerContextRequestHandlerTest;
   friend class service_worker_controllee_request_handler_unittest::
       ServiceWorkerControlleeRequestHandlerTest;
   friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.h b/content/browser/service_worker/service_worker_read_from_cache_job.h
index 6509d478..c2aa051 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job.h
+++ b/content/browser/service_worker/service_worker_read_from_cache_job.h
@@ -41,8 +41,6 @@
 
  private:
   friend class ServiceWorkerReadFromCacheJobTest;
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
-                           DuplicateScriptImport);
 
   bool is_main_script() const {
     return resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index a9961fa..3892721 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -31,7 +31,6 @@
 #include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_client_info.h"
 #include "content/browser/service_worker/service_worker_client_utils.h"
-#include "content/browser/service_worker/service_worker_context_request_handler.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/browser/service_worker/service_worker_ping_controller.h"
 #include "content/browser/service_worker/service_worker_script_cache_map.h"
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.h b/content/browser/service_worker/service_worker_write_to_cache_job.h
index 5c18785..35b7f83 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job.h
+++ b/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -26,7 +26,6 @@
 
 class ServiceWorkerCacheWriter;
 class ServiceWorkerContextCore;
-class ServiceWorkerContextRequestHandlerTest;
 
 // A URLRequestJob derivative used to cache the main script
 // and its imports during the initial install of a new version.
@@ -61,10 +60,6 @@
   const static net::Error kIdenticalScriptError;
 
  private:
-  friend class ServiceWorkerContextRequestHandlerTest;
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
-                           ServiceWorkerDataRequestAnnotation);
-
   ~ServiceWorkerWriteToCacheJob() override;
 
   // net::URLRequestJob overrides
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
index c13bc8a..ef4cacf 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -17,10 +17,10 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_context_request_handler.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/test/test_browser_thread_bundle.h"
diff --git a/content/browser/web_package/signed_exchange_loader.cc b/content/browser/web_package/signed_exchange_loader.cc
index b27c2e0a..86d0026e9 100644
--- a/content/browser/web_package/signed_exchange_loader.cc
+++ b/content/browser/web_package/signed_exchange_loader.cc
@@ -45,8 +45,7 @@
 net::RedirectInfo CreateRedirectInfo(
     const GURL& new_url,
     const network::ResourceRequest& outer_request,
-    const network::ResourceResponseHead& outer_response,
-    bool is_fallback_redirect) {
+    const network::ResourceResponseHead& outer_response) {
   // https://wicg.github.io/webpackage/loading.html#mp-http-fetch
   // Step 3. Set actualResponse's status to 303. [spec text]
   return net::RedirectInfo::ComputeRedirectInfo(
@@ -59,8 +58,7 @@
       outer_request.referrer_policy, outer_request.referrer.spec(), 303,
       new_url,
       net::RedirectUtil::GetReferrerPolicyHeader(outer_response.headers.get()),
-      false /* insecure_scheme_was_upgraded */, true /* copy_fragment */,
-      is_fallback_redirect);
+      false /* insecure_scheme_was_upgraded */);
 }
 
 bool HasNoSniffHeader(const network::ResourceResponseHead& response) {
@@ -304,8 +302,7 @@
     fallback_url_ = request_url;
     DCHECK(outer_response_timing_info_);
     forwarding_client_->OnReceiveRedirect(
-        CreateRedirectInfo(request_url, outer_request_, outer_response_,
-                           true /* is_fallback_redirect */),
+        CreateRedirectInfo(request_url, outer_request_, outer_response_),
         std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
     forwarding_client_.reset();
     return;
@@ -315,8 +312,7 @@
 
   DCHECK(outer_response_timing_info_);
   forwarding_client_->OnReceiveRedirect(
-      CreateRedirectInfo(request_url, outer_request_, outer_response_,
-                         false /* is_fallback_redirect */),
+      CreateRedirectInfo(request_url, outer_request_, outer_response_),
       std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
   forwarding_client_.reset();
 
diff --git a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index d0eac74..59a9a894 100644
--- a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -771,8 +771,6 @@
     https_server_.ServeFilesFromSourceDirectory("content/test/data");
     https_server_.RegisterRequestHandler(
         base::BindRepeating(&self::RedirectResponseHandler));
-    https_server_.RegisterRequestHandler(
-        base::BindRepeating(&self::FallbackSxgResponseHandler));
     https_server_.RegisterRequestMonitor(
         base::BindRepeating(&self::MonitorRequest, base::Unretained(this)));
     ASSERT_TRUE(https_server_.Start());
@@ -787,16 +785,16 @@
     EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
   }
 
-  bool IsSignedExchangeEnabled() const { return GetParam(); }
+  bool ShouldHaveSXGAcceptHeaderInEnabledOrigin() const { return GetParam(); }
 
-  void CheckAcceptHeader(const GURL& url,
-                         bool is_navigation,
-                         bool is_fallback) {
+  bool ShouldHaveSXGAcceptHeader() const { return GetParam(); }
+
+  void CheckAcceptHeader(const GURL& url, bool is_navigation) {
     const auto accept_header = GetInterceptedAcceptHeader(url);
     ASSERT_TRUE(accept_header);
     EXPECT_EQ(
         *accept_header,
-        IsSignedExchangeEnabled() && !is_fallback
+        ShouldHaveSXGAcceptHeader()
             ? (is_navigation
                    ? std::string(network::kFrameAcceptHeader) +
                          std::string(kAcceptHeaderSignedExchangeSuffix)
@@ -808,22 +806,14 @@
   void CheckNavigationAcceptHeader(const std::vector<GURL>& urls) {
     for (const auto& url : urls) {
       SCOPED_TRACE(url);
-      CheckAcceptHeader(url, true /* is_navigation */, false /* is_fallback */);
+      CheckAcceptHeader(url, true /* is_navigation */);
     }
   }
 
   void CheckPrefetchAcceptHeader(const std::vector<GURL>& urls) {
     for (const auto& url : urls) {
       SCOPED_TRACE(url);
-      CheckAcceptHeader(url, false /* is_navigation */,
-                        false /* is_fallback */);
-    }
-  }
-
-  void CheckFallbackAcceptHeader(const std::vector<GURL>& urls) {
-    for (const auto& url : urls) {
-      SCOPED_TRACE(url);
-      CheckAcceptHeader(url, true /* is_navigation */, true /* is_fallback */);
+      CheckAcceptHeader(url, false /* is_navigation */);
     }
   }
 
@@ -854,33 +844,6 @@
     return std::move(http_response);
   }
 
-  // Responds with a prologue-only signed exchange that triggers a fallback
-  // redirect.
-  static std::unique_ptr<net::test_server::HttpResponse>
-  FallbackSxgResponseHandler(const net::test_server::HttpRequest& request) {
-    const std::string prefix = "/fallback_sxg?";
-    if (!base::StartsWith(request.relative_url, prefix,
-                          base::CompareCase::SENSITIVE)) {
-      return std::unique_ptr<net::test_server::HttpResponse>();
-    }
-    std::string fallback_url(request.relative_url.substr(prefix.length()));
-
-    std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
-        new net::test_server::BasicHttpResponse);
-    http_response->set_code(net::HTTP_OK);
-    http_response->set_content_type("application/signed-exchange;v=b3");
-
-    std::string sxg("sxg1-b3", 8);
-    sxg.push_back(fallback_url.length() >> 8);
-    sxg.push_back(fallback_url.length() & 0xff);
-    sxg += fallback_url;
-    // FallbackUrlAndAfter() requires 6 more bytes for sizes of next fields.
-    sxg.resize(sxg.length() + 6);
-
-    http_response->set_content(sxg);
-    return std::move(http_response);
-  }
-
   void MonitorRequest(const net::test_server::HttpRequest& request) {
     const auto it = request.headers.find(std::string(network::kAcceptHeader));
     if (it == request.headers.end())
@@ -897,7 +860,7 @@
 
 IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest, Simple) {
   const GURL test_url = https_server_.GetURL("/sxg/test.html");
-  EXPECT_EQ(IsSignedExchangeEnabled(),
+  EXPECT_EQ(ShouldHaveSXGAcceptHeaderInEnabledOrigin(),
             signed_exchange_utils::IsSignedExchangeHandlingEnabled());
   NavigateAndWaitForTitle(test_url, test_url.spec());
   CheckNavigationAcceptHeader({test_url});
@@ -914,20 +877,6 @@
 }
 
 IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
-                       FallbackRedirect) {
-  if (!IsSignedExchangeEnabled())
-    return;
-
-  const GURL fallback_url = https_server_.GetURL("/sxg/test.html");
-  const GURL test_url =
-      https_server_.GetURL("/fallback_sxg?" + fallback_url.spec());
-  NavigateAndWaitForTitle(test_url, fallback_url.spec());
-
-  CheckNavigationAcceptHeader({test_url});
-  CheckFallbackAcceptHeader({fallback_url});
-}
-
-IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
                        PrefetchEnabledPageEnabledTarget) {
   const GURL target = https_server_.GetURL("/sxg/hello.txt");
   const GURL page_url =
@@ -973,12 +922,13 @@
 
     const std::string expected_title =
         is_generated_scope
-            ? (IsSignedExchangeEnabled() ? frame_accept_with_sxg : frame_accept)
+            ? (ShouldHaveSXGAcceptHeader() ? frame_accept_with_sxg
+                                           : frame_accept)
             : "Done";
     const base::Optional<std::string> expected_target_accept_header =
         is_generated_scope
             ? base::nullopt
-            : base::Optional<std::string>(IsSignedExchangeEnabled()
+            : base::Optional<std::string>(ShouldHaveSXGAcceptHeader()
                                               ? frame_accept_with_sxg
                                               : frame_accept);
 
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 487194d..e2c91ea0 100644
--- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -876,14 +876,6 @@
   ExecuteJavascriptAndWaitForOk("verifyAfterAudioServiceCrash()");
 }
 
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
-                       GetUserMediaCloneAndApplyConstraints) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
-  NavigateToURL(shell(), url);
-  ExecuteJavascriptAndWaitForOk("getUserMediaCloneAndApplyConstraints()");
-}
-
 // We run these tests with the audio service both in and out of the the browser
 // process to have waterfall coverage while the feature rolls out. It should be
 // removed after launch.
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc
index 52a723f..ad71e04 100644
--- a/content/browser/worker_host/worker_script_loader.cc
+++ b/content/browser/worker_host/worker_script_loader.cc
@@ -9,6 +9,7 @@
 #include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
 #include "content/public/browser/resource_context.h"
 #include "net/url_request/redirect_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/content/common/origin_util.cc b/content/common/origin_util.cc
index 878cb24a..422c62e2 100644
--- a/content/common/origin_util.cc
+++ b/content/common/origin_util.cc
@@ -10,6 +10,7 @@
 #include "base/strings/pattern.h"
 #include "content/common/url_schemes.h"
 #include "net/base/url_util.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "url/gurl.h"
 #include "url/url_util.h"
 
@@ -43,18 +44,8 @@
   if (base::ContainsValue(url::GetSecureSchemes(), url.scheme()))
     return true;
 
-  return IsWhitelistedAsSecureOrigin(url::Origin::Create(url));
-}
-
-bool IsWhitelistedAsSecureOrigin(const url::Origin& origin) {
-  if (base::ContainsValue(content::GetSecureOriginsAndPatterns(),
-                          origin.Serialize()))
-    return true;
-  for (const auto& origin_or_pattern : content::GetSecureOriginsAndPatterns()) {
-    if (base::MatchPattern(origin.host(), origin_or_pattern))
-      return true;
-  }
-  return false;
+  return network::IsAllowlistedAsSecureOrigin(
+      url::Origin::Create(url), network::GetSecureOriginAllowlist());
 }
 
 bool OriginCanAccessServiceWorkers(const GURL& url) {
@@ -83,7 +74,8 @@
     return true;
   }
 
-  return IsWhitelistedAsSecureOrigin(origin);
+  return network::IsAllowlistedAsSecureOrigin(
+      origin, network::GetSecureOriginAllowlist());
 }
 
 }  // namespace content
diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
index e532406..6c6bf27 100644
--- a/content/common/url_schemes.cc
+++ b/content/common/url_schemes.cc
@@ -7,6 +7,7 @@
 #include <string.h>
 
 #include <iterator>
+#include <utility>
 
 #include "base/no_destructor.h"
 #include "base/strings/string_util.h"
@@ -39,11 +40,6 @@
 
 // This set contains serialized canonicalized origins as well as hostname
 // patterns. The latter are canonicalized by component.
-std::vector<std::string>& GetMutableSecureOriginsAndPatterns() {
-  static base::NoDestructor<std::vector<std::string>> origins;
-  return *origins;
-}
-
 std::vector<std::string>& GetMutableServiceWorkerSchemes() {
   static base::NoDestructor<std::vector<std::string>> schemes;
   return *schemes;
@@ -111,18 +107,12 @@
                                     schemes.savable_schemes.end());
 
   GetMutableServiceWorkerSchemes() = std::move(schemes.service_worker_schemes);
-
-  GetMutableSecureOriginsAndPatterns() = std::move(schemes.secure_origins);
 }
 
 const std::vector<std::string>& GetSavableSchemes() {
   return GetMutableSavableSchemes();
 }
 
-const std::vector<std::string>& GetSecureOriginsAndPatterns() {
-  return GetMutableSecureOriginsAndPatterns();
-}
-
 const std::vector<std::string>& GetServiceWorkerSchemes() {
   return GetMutableServiceWorkerSchemes();
 }
diff --git a/content/common/url_schemes.h b/content/common/url_schemes.h
index 802c80b..407d6f5 100644
--- a/content/common/url_schemes.h
+++ b/content/common/url_schemes.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "content/common/content_export.h"
-#include "url/origin.h"
 
 namespace content {
 
@@ -28,11 +27,6 @@
 // See comment in ContentClient::AddAdditionalSchemes for explanations. These
 // getters can be invoked on any thread.
 const std::vector<std::string>& GetSavableSchemes();
-// Contains serialized canonicalized origins as well as hostname patterns such
-// as "*.foo.com". An origin should be considered secure if it matches an origin
-// in this list or if its hostname matches one of the hostname patterns. The
-// hostname patterns are canonicalized by component.
-const std::vector<std::string>& GetSecureOriginsAndPatterns();
 const std::vector<std::string>& GetServiceWorkerSchemes();
 
 }  // namespace content
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index b4217dc..ed16a41 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -76,8 +76,8 @@
     "//services/shape_detection:shape_detection_java",
     "//services/shape_detection/public/mojom:mojom_java",
     "//skia/public/interfaces:interfaces_java",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
     "//third_party/blink/public:android_mojo_bindings_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:mojom_core_java",
@@ -476,7 +476,7 @@
     "//services/device/public/java:geolocation_java_test_support",
     "//services/service_manager/public/java:service_manager_java",
     "//services/test/echo/public/mojom:mojom_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/blink/public:android_mojo_bindings_java",
diff --git a/content/public/browser/background_sync_context.h b/content/public/browser/background_sync_context.h
index f4ec66a3..fd7c4064 100644
--- a/content/public/browser/background_sync_context.h
+++ b/content/public/browser/background_sync_context.h
@@ -7,9 +7,16 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#endif
 
 namespace content {
 
+class BrowserContext;
 class StoragePartition;
 
 // One instance of this exists per StoragePartition, and services multiple child
@@ -20,13 +27,30 @@
  public:
   BackgroundSyncContext() = default;
 
-  // Process any pending Background Sync registrations for |storage_partition|.
+  // Process any pending Background Sync registrations.
   // This involves firing any sync events ready to be fired, and optionally
   // scheduling a job to wake up the browser when the next event needs to be
   // fired.
-  virtual void FireBackgroundSyncEventsForStoragePartition(
-      StoragePartition* storage_partition,
-      base::OnceClosure done_closure) = 0;
+  virtual void FireBackgroundSyncEvents(base::OnceClosure done_closure) = 0;
+
+#if defined(OS_ANDROID)
+  // Processes pending Background Sync registrations for all storage partitions
+  // in |browser_context|, and then runs  the |j_runnable| when done.
+  virtual void FireBackgroundSyncEventsAcrossPartitions(
+      BrowserContext* browser_context,
+      const base::android::JavaParamRef<jobject>& j_runnable) = 0;
+#endif
+
+  // Gets the soonest time delta from now, when the browser should be woken up
+  // to fire any Background Sync events.
+  virtual base::TimeDelta GetSoonestWakeupDelta() = 0;
+
+  // Gets the soonest time delta from now, when the browser should be woken up
+  // to fire any Background Sync events, across all storage partitions in
+  // |browser_context|, and invokes |callback| with it.
+  virtual void GetSoonestWakeupDeltaAcrossPartitions(
+      BrowserContext* browser_context,
+      base::OnceCallback<void(base::TimeDelta)> callback) = 0;
 
  protected:
   virtual ~BackgroundSyncContext() = default;
diff --git a/content/public/browser/background_sync_controller.h b/content/public/browser/background_sync_controller.h
index 33ad82d..50e6c4064 100644
--- a/content/public/browser/background_sync_controller.h
+++ b/content/public/browser/background_sync_controller.h
@@ -33,16 +33,9 @@
   // registered a background sync event.
   virtual void NotifyBackgroundSyncRegistered(const url::Origin& origin) {}
 
-  // If |enabled|, ensures that the browser is running when the device next goes
-  // online after |min_ms| has passed. The behavior is platform dependent:
-  // * Android: Registers a GCM task which verifies that the browser is running
-  // the next time the device goes online after |min_ms| has passed. If it's
-  // not, it starts it.
-  //
-  // * Other Platforms: (UNIMPLEMENTED) Keeps the browser alive via
-  // BackgroundModeManager until called with |enabled| = false. |min_ms| is
-  // ignored.
-  virtual void RunInBackground(bool enabled, int64_t min_ms) {}
+  // Calculates the soonest wakeup delta across all storage partitions and
+  // schedules a background task to wake up the browser.
+  virtual void RunInBackground() {}
 };
 
 }  // namespace content
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
index bfe6deb..394936e 100644
--- a/content/public/common/content_client.h
+++ b/content/public/common/content_client.h
@@ -135,9 +135,6 @@
     std::vector<std::string> csp_bypassing_schemes;
     // See https://www.w3.org/TR/powerful-features/#is-origin-trustworthy.
     std::vector<std::string> secure_schemes;
-    // Registers a serialized origin or a hostname pattern that should be
-    // considered trustworthy.
-    std::vector<std::string> secure_origins;
     // Registers a URL scheme as strictly empty documents, allowing them to
     // commit synchronously.
     std::vector<std::string> empty_document_schemes;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index a6e748b..6f34b5b 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -220,6 +220,12 @@
 // the use of persistent gpu memory buffers.
 const char kDisablePartialRaster[] = "disable-partial-raster";
 
+// Internally (in devtools_session.cc) switches the protocol to binary format
+// (CBOR). This setting is temporary; we plan to remove it after transition to
+// binary is sufficiently complete (2019-04-01).
+const char kEnableInternalDevToolsBinaryProtocol[] =
+    "enable-internal-devtools-binary-protocol";
+
 // Enable partial raster in the renderer.
 const char kEnablePartialRaster[] = "enable-partial-raster";
 
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index b298c312..69ad632 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -75,6 +75,7 @@
 CONTENT_EXPORT extern const char kDisableNotifications[];
 CONTENT_EXPORT extern const char kDisableOriginTrialControlledBlinkFeatures[];
 CONTENT_EXPORT extern const char kDisablePartialRaster[];
+CONTENT_EXPORT extern const char kEnableInternalDevToolsBinaryProtocol[];
 CONTENT_EXPORT extern const char kEnablePartialRaster[];
 extern const char kDisablePepper3d[];
 CONTENT_EXPORT extern const char kDisablePepper3DImageChromium[];
diff --git a/content/public/common/origin_util.h b/content/public/common/origin_util.h
index 4e4bbc3a9..bb4a389a 100644
--- a/content/public/common/origin_util.h
+++ b/content/public/common/origin_util.h
@@ -23,10 +23,6 @@
 // may be insecure iframes present even if this method returns true.
 bool CONTENT_EXPORT IsOriginSecure(const GURL& url);
 
-// Returns true if |origin| is whitelisted as secure, e.g. it was specified via
-// the --unsafely-treat-insecure-origin-as-secure flag, and false otherwise.
-bool CONTENT_EXPORT IsWhitelistedAsSecureOrigin(const url::Origin& origin);
-
 // Returns true if the origin can register a service worker.  Scheme must be
 // http (localhost only), https, or a custom-set secure scheme.
 bool CONTENT_EXPORT OriginCanAccessServiceWorkers(const GURL& url);
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
index c6e998d..dfc42c5 100644
--- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc
+++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -309,9 +309,9 @@
         embed_render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
     shared_quad_state->SetAll(
         child_transform, gfx::Rect(child_size), gfx::Rect(child_size),
-        gfx::Rect() /* clip_rect */, false /* is_clipped */,
-        are_contents_opaque /* are_contents_opaque */, 1.f /* opacity */,
-        SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
+        gfx::RRectF() /* rounded_corner_bounds */, gfx::Rect() /* clip_rect */,
+        false /* is_clipped */, are_contents_opaque /* are_contents_opaque */,
+        1.f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
     surface_quad->SetNew(
         shared_quad_state, gfx::Rect(child_size), gfx::Rect(child_size),
         viz::SurfaceRange(
diff --git a/content/renderer/media/webrtc/rtc_video_decoder.cc b/content/renderer/media/webrtc/rtc_video_decoder.cc
index 7a71afae..7705e72 100644
--- a/content/renderer/media/webrtc/rtc_video_decoder.cc
+++ b/content/renderer/media/webrtc/rtc_video_decoder.cc
@@ -13,6 +13,7 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task_runner_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
 #include "gpu/command_buffer/common/mailbox_holder.h"
@@ -136,6 +137,9 @@
       return decoder;
   }
 
+  // This wait is necessary because this task is completed in GPU process
+  // asynchronously but WebRTC API is synchronous.
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
   decoder.reset(new RTCVideoDecoder(type, factories));
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
index 9c4d2799..ad53e97 100644
--- a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
+++ b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -19,6 +19,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/renderer/media/render_media_log.h"
@@ -196,6 +197,7 @@
   // Can be called on |worker_thread_| or |decoding_thread_|.
   DCHECK(!media_task_runner_->BelongsToCurrentThread());
 
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   bool result = false;
   base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -444,6 +446,7 @@
     const media::VideoDecoderConfig& config) {
   DCHECK_CALLED_ON_VALID_THREAD(decoding_thread_checker_);
 
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   bool result = false;
   base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
diff --git a/content/renderer/media/webrtc/rtc_video_encoder.cc b/content/renderer/media/webrtc/rtc_video_encoder.cc
index d24ff0c..5d5ce77 100644
--- a/content/renderer/media/webrtc/rtc_video_encoder.cc
+++ b/content/renderer/media/webrtc/rtc_video_encoder.cc
@@ -21,6 +21,7 @@
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_checker.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "content/public/common/content_features.h"
@@ -888,6 +889,9 @@
                    ? webrtc::VideoContentType::SCREENSHARE
                    : webrtc::VideoContentType::UNSPECIFIED);
 
+  // This wait is necessary because this task is completed in GPU process
+  // asynchronously but WebRTC API is synchronous.
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   base::WaitableEvent initialization_waiter(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -917,6 +921,7 @@
 
   const bool want_key_frame = frame_types && frame_types->size() &&
                               frame_types->front() == webrtc::kVideoFrameKey;
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   base::WaitableEvent encode_waiter(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -940,6 +945,7 @@
     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
   }
 
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   base::WaitableEvent register_waiter(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -957,6 +963,7 @@
   if (!impl_.get())
     return WEBRTC_VIDEO_CODEC_OK;
 
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
   base::WaitableEvent release_waiter(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 28a2ffa..894bf91 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1385,6 +1385,7 @@
     "../browser/background_fetch/background_fetch_service_unittest.cc",
     "../browser/background_fetch/storage/database_helpers_unittest.cc",
     "../browser/background_fetch/storage/image_helpers_unittest.cc",
+    "../browser/background_sync/background_sync_launcher_unittest.cc",
     "../browser/background_sync/background_sync_manager_unittest.cc",
     "../browser/background_sync/background_sync_network_observer_unittest.cc",
     "../browser/background_sync/background_sync_service_impl_unittest.cc",
@@ -1922,6 +1923,7 @@
     "//content/browser/background_fetch:background_fetch_proto",
     "//content/browser/cache_storage:cache_storage_proto",
     "//content/browser/devtools:devtools_background_services_proto",
+    "//content/browser/devtools:inspector_protocol_encoding_test",
     "//content/browser/dom_storage:local_storage_proto",
     "//content/browser/notifications:notification_proto",
     "//content/browser/service_worker:service_worker_proto",
diff --git a/content/test/data/media/getusermedia.html b/content/test/data/media/getusermedia.html
index 05085f5b..23e2568 100644
--- a/content/test/data/media/getusermedia.html
+++ b/content/test/data/media/getusermedia.html
@@ -916,38 +916,6 @@
     }
   }
 
-  function playStreamAndGetElement(stream) {
-    v = document.createElement("video");
-    document.body.append(v);
-    v.srcObject = stream;
-    v.play();
-    return v;
-  }
-
-  async function getUserMediaCloneAndApplyConstraints() {
-    const stream = await navigator.mediaDevices.getUserMedia({video: { width: 640, height: 480 }});
-    const video = playStreamAndGetElement(stream);
-
-    const clone1 = stream.clone();
-    await clone1.getVideoTracks()[0].applyConstraints({width: 500, height: 500});
-    const video1 = playStreamAndGetElement(clone1);
-
-    const clone2 = stream.clone();
-    await clone2.getVideoTracks()[0].applyConstraints({width: 100, height: 100});
-    const video2 = playStreamAndGetElement(clone2);
-
-    var numFrames = 0;
-    var numOnProgress = 0;
-    video2.onprogress = () => {
-      numFrames += video2.webkitDecodedFrameCount;
-      ++numOnProgress;
-      if (numFrames >= 1)
-        reportTestSuccess();
-      if (numOnProgress > 1)
-        failTest("track from cloned stream is not producing any frames");
-    }
-  }
-
   </script>
 </head>
 <body>
diff --git a/content/test/mock_background_sync_controller.cc b/content/test/mock_background_sync_controller.cc
index 13b94930..b671965 100644
--- a/content/test/mock_background_sync_controller.cc
+++ b/content/test/mock_background_sync_controller.cc
@@ -12,11 +12,8 @@
   registration_origin_ = origin;
 }
 
-void MockBackgroundSyncController::RunInBackground(bool enabled,
-                                                   int64_t min_ms) {
+void MockBackgroundSyncController::RunInBackground() {
   run_in_background_count_ += 1;
-  run_in_background_enabled_ = enabled;
-  run_in_background_min_ms_ = min_ms;
 }
 
 void MockBackgroundSyncController::GetParameterOverrides(
diff --git a/content/test/mock_background_sync_controller.h b/content/test/mock_background_sync_controller.h
index 0a854ea..3f97681 100644
--- a/content/test/mock_background_sync_controller.h
+++ b/content/test/mock_background_sync_controller.h
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/time/time.h"
 #include "content/public/browser/background_sync_controller.h"
 #include "content/public/browser/background_sync_parameters.h"
 #include "url/gurl.h"
@@ -24,7 +25,7 @@
 
   // BackgroundSyncController:
   void NotifyBackgroundSyncRegistered(const url::Origin& origin) override;
-  void RunInBackground(bool enabled, int64_t min_ms) override;
+  void RunInBackground() override;
   void GetParameterOverrides(
       BackgroundSyncParameters* parameters) const override;
 
@@ -33,8 +34,6 @@
     return registration_origin_;
   }
   int run_in_background_count() const { return run_in_background_count_; }
-  bool run_in_background_enabled() const { return run_in_background_enabled_; }
-  int64_t run_in_background_min_ms() const { return run_in_background_min_ms_; }
   BackgroundSyncParameters* background_sync_parameters() {
     return &background_sync_parameters_;
   }
@@ -44,8 +43,6 @@
   url::Origin registration_origin_;
 
   int run_in_background_count_ = 0;
-  bool run_in_background_enabled_ = true;
-  int64_t run_in_background_min_ms_ = 0;
   BackgroundSyncParameters background_sync_parameters_;
 
   DISALLOW_COPY_AND_ASSIGN(MockBackgroundSyncController);
diff --git a/content/test/test_background_sync_manager.cc b/content/test/test_background_sync_manager.cc
index 3e95d08..0635711 100644
--- a/content/test/test_background_sync_manager.cc
+++ b/content/test/test_background_sync_manager.cc
@@ -118,4 +118,9 @@
   BackgroundSyncManager::GetDataFromBackend(key, std::move(callback));
 }
 
+base::TimeDelta TestBackgroundSyncManager::GetSoonestWakeupDelta() {
+  soonest_wakeup_delta_ = BackgroundSyncManager::GetSoonestWakeupDelta();
+  return soonest_wakeup_delta_;
+}
+
 }  // namespace content
diff --git a/content/test/test_background_sync_manager.h b/content/test/test_background_sync_manager.h
index a4566e0c..4fd6508c 100644
--- a/content/test/test_background_sync_manager.h
+++ b/content/test/test_background_sync_manager.h
@@ -86,6 +86,13 @@
     return parameters_.get();
   }
 
+  bool IsBrowserWakeupScheduled() const {
+    return !soonest_wakeup_delta_.is_max();
+  }
+  bool EqualsSoonestWakeupDelta(base::TimeDelta compare_to) const {
+    return soonest_wakeup_delta_ == compare_to;
+  }
+
  protected:
   // Override to allow delays to be injected by tests.
   void StoreDataInBackend(
@@ -119,6 +126,8 @@
   void HasMainFrameProviderHost(const url::Origin& origin,
                                 BoolCallback callback) override;
 
+  base::TimeDelta GetSoonestWakeupDelta() override;
+
  private:
   // Callback to resume the StoreDataInBackend operation, after explicit
   // delays injected by tests.
@@ -143,6 +152,7 @@
   DispatchSyncCallback dispatch_sync_callback_;
   base::OnceClosure delayed_task_;
   base::TimeDelta delayed_task_delta_;
+  base::TimeDelta soonest_wakeup_delta_;
 
   DISALLOW_COPY_AND_ASSIGN(TestBackgroundSyncManager);
 };
diff --git a/courgette/disassembler.h b/courgette/disassembler.h
index 5b1bb8de..78a4005f 100644
--- a/courgette/disassembler.h
+++ b/courgette/disassembler.h
@@ -115,7 +115,12 @@
   bool Good();
   bool Bad(const char *reason);
 
-  // Returns true if the array lies within our memory region.
+  // Returns true if the given range lies within our memory region.
+  bool IsRangeInBounds(size_t offset, size_t size) {
+    return offset <= length() && size <= length() - offset;
+  }
+
+  // Returns true if the given array lies within our memory region.
   bool IsArrayInBounds(size_t offset, size_t elements, size_t element_size) {
     return offset <= length() && elements <= (length() - offset) / element_size;
   }
diff --git a/courgette/disassembler_elf_32.cc b/courgette/disassembler_elf_32.cc
index fac661c7..e5852080 100644
--- a/courgette/disassembler_elf_32.cc
+++ b/courgette/disassembler_elf_32.cc
@@ -101,28 +101,36 @@
 
   header_ = reinterpret_cast<const Elf32_Ehdr*>(start());
 
-  // Have magic for ELF header?
-  if (header_->e_ident[0] != 0x7f ||
-      header_->e_ident[1] != 'E' ||
-      header_->e_ident[2] != 'L' ||
-      header_->e_ident[3] != 'F')
-    return Bad("No Magic Number");
+  // Perform DisassemblerElf32::QuickDetect() checks (with error messages).
 
-  if (header_->e_type != ET_EXEC &&
-      header_->e_type != ET_DYN)
+  // Have magic for ELF header?
+  if (header_->e_ident[EI_MAG0] != 0x7F || header_->e_ident[EI_MAG1] != 'E' ||
+      header_->e_ident[EI_MAG2] != 'L' || header_->e_ident[EI_MAG3] != 'F') {
+    return Bad("No Magic Number");
+  }
+
+  if (header_->e_ident[EI_CLASS] != ELFCLASS32 ||
+      header_->e_ident[EI_DATA] != ELFDATA2LSB ||
+      header_->e_machine != ElfEM()) {
+    return Bad("Not a supported architecture");
+  }
+
+  if (header_->e_type != ET_EXEC && header_->e_type != ET_DYN)
     return Bad("Not an executable file or shared library");
 
-  if (header_->e_machine != ElfEM())
-    return Bad("Not a supported architecture");
-
-  if (header_->e_version != 1)
+  if (header_->e_version != 1 || header_->e_ident[EI_VERSION] != 1)
     return Bad("Unknown file version");
 
   if (header_->e_shentsize != sizeof(Elf32_Shdr))
     return Bad("Unexpected section header size");
 
-  if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
+  // Perform more complex checks, while extracting data.
+
+  if (header_->e_shoff < sizeof(Elf32_Ehdr) ||
+      !IsArrayInBounds(header_->e_shoff, header_->e_shnum,
+                       sizeof(Elf32_Shdr))) {
     return Bad("Out of bounds section header table");
+  }
 
   // Extract |section_header_table_|, ordered by section id.
   const Elf32_Shdr* section_header_table_raw =
@@ -131,34 +139,41 @@
   section_header_table_size_ = header_->e_shnum;
   section_header_table_.assign(section_header_table_raw,
       section_header_table_raw + section_header_table_size_);
-
-  // TODO(huangs): Validate offsets of all section headers.
-
+  if (!CheckSectionRanges())
+    return Bad("Out of bound section");
   section_header_file_offset_order_ =
       GetSectionHeaderFileOffsetOrder(section_header_table_);
-
-  if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
+  if (header_->e_phoff < sizeof(Elf32_Ehdr) ||
+      !IsArrayInBounds(header_->e_phoff, header_->e_phnum,
+                       sizeof(Elf32_Phdr))) {
     return Bad("Out of bounds program header table");
+  }
 
+  // Extract |program_header_table_|.
+  program_header_table_size_ = header_->e_phnum;
   program_header_table_ = reinterpret_cast<const Elf32_Phdr*>(
       FileOffsetToPointer(header_->e_phoff));
-  program_header_table_size_ = header_->e_phnum;
+  if (!CheckProgramSegmentRanges())
+    return Bad("Out of bound segment");
 
+  // Extract |default_string_section_|.
   Elf32_Half string_section_id = header_->e_shstrndx;
+  if (string_section_id == SHN_UNDEF)
+    return Bad("Missing string section");
   if (string_section_id >= header_->e_shnum)
     return Bad("Out of bounds string section index");
-
+  if (SectionHeader(string_section_id)->sh_type != SHT_STRTAB)
+    return Bad("Invalid string section");
+  default_string_section_size_ = SectionHeader(string_section_id)->sh_size;
   default_string_section_ =
       reinterpret_cast<const char*>(SectionBody(string_section_id));
-  default_string_section_size_ = SectionHeader(string_section_id)->sh_size;
   // String section may be empty. If nonempty, then last byte must be null.
   if (default_string_section_size_ > 0) {
     if (default_string_section_[default_string_section_size_ - 1] != '\0')
       return Bad("String section does not terminate");
   }
 
-  if (!UpdateLength())
-    return Bad("Out of bounds section or segment");
+  UpdateLength();
 
   return Good();
 }
@@ -195,15 +210,17 @@
   const Elf32_Ehdr* header = reinterpret_cast<const Elf32_Ehdr*>(start);
 
   // Have magic for ELF header?
-  if (header->e_ident[0] != 0x7f || header->e_ident[1] != 'E' ||
-      header->e_ident[2] != 'L' || header->e_ident[3] != 'F')
+  if (header->e_ident[EI_MAG0] != 0x7F || header->e_ident[EI_MAG1] != 'E' ||
+      header->e_ident[EI_MAG2] != 'L' || header->e_ident[EI_MAG3] != 'F') {
     return false;
-
+  }
+  if (header->e_ident[EI_CLASS] != ELFCLASS32 ||
+      header->e_ident[EI_DATA] != ELFDATA2LSB || header->e_machine != elf_em) {
+    return false;
+  }
   if (header->e_type != ET_EXEC && header->e_type != ET_DYN)
     return false;
-  if (header->e_machine != elf_em)
-    return false;
-  if (header->e_version != 1)
+  if (header->e_version != 1 || header->e_ident[EI_VERSION] != 1)
     return false;
   if (header->e_shentsize != sizeof(Elf32_Shdr))
     return false;
@@ -211,32 +228,47 @@
   return true;
 }
 
-bool DisassemblerElf32::UpdateLength() {
-  Elf32_Off result = 0;
-
-  // Find the end of the last section
+bool DisassemblerElf32::CheckSectionRanges() {
   for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
        ++section_id) {
     const Elf32_Shdr* section_header = SectionHeader(section_id);
+    if (section_header->sh_type == SHT_NOBITS)  // E.g., .bss.
+      continue;
+    if (!IsRangeInBounds(section_header->sh_offset, section_header->sh_size))
+      return false;
+  }
+  return true;
+}
 
+bool DisassemblerElf32::CheckProgramSegmentRanges() {
+  for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
+       ++segment_id) {
+    const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
+    if (!IsRangeInBounds(segment_header->p_offset, segment_header->p_filesz))
+      return false;
+  }
+  return true;
+}
+
+void DisassemblerElf32::UpdateLength() {
+  Elf32_Off result = 0;
+
+  // Find the end of the last section.
+  for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
+       ++section_id) {
+    const Elf32_Shdr* section_header = SectionHeader(section_id);
     if (section_header->sh_type == SHT_NOBITS)
       continue;
-
-    if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
-      return false;
-
+    DCHECK(IsRangeInBounds(section_header->sh_offset, section_header->sh_size));
     Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
     result = std::max(result, section_end);
   }
 
-  // Find the end of the last segment
+  // Find the end of the last segment.
   for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
        ++segment_id) {
     const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
-
-    if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
-      return false;
-
+    DCHECK(IsRangeInBounds(segment_header->p_offset, segment_header->p_filesz));
     Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
     result = std::max(result, segment_end);
   }
@@ -250,7 +282,6 @@
   result = std::max(result, segment_table_end);
 
   ReduceLength(result);
-  return true;
 }
 
 CheckBool DisassemblerElf32::SectionName(const Elf32_Shdr& shdr,
diff --git a/courgette/disassembler_elf_32.h b/courgette/disassembler_elf_32.h
index a75773d..fba67f1 100644
--- a/courgette/disassembler_elf_32.h
+++ b/courgette/disassembler_elf_32.h
@@ -129,7 +129,13 @@
                           size_t length,
                           e_machine_values elf_em);
 
-  bool UpdateLength();
+  // Returns whether all non-SHT_NOBITS sections lie within image.
+  bool CheckSectionRanges();
+
+  // Returns whether all program segments lie within image.
+  bool CheckProgramSegmentRanges();
+
+  void UpdateLength();
 
   // Misc Section Helpers
 
@@ -143,8 +149,9 @@
   }
 
   const uint8_t* SectionBody(Elf32_Half id) const {
-    // TODO(huangs): Assert that section does not have SHT_NOBITS.
-    return FileOffsetToPointer(SectionHeader(id)->sh_offset);
+    const Elf32_Shdr* section_header = SectionHeader(id);
+    DCHECK(section_header->sh_type != SHT_NOBITS);
+    return FileOffsetToPointer(section_header->sh_offset);
   }
 
   // Gets the |name| of section |shdr|. Returns true on success.
diff --git a/courgette/types_elf.h b/courgette/types_elf.h
index a98fd8b..d45a10e 100644
--- a/courgette/types_elf.h
+++ b/courgette/types_elf.h
@@ -36,6 +36,35 @@
   Elf32_Half     e_shstrndx;
 };
 
+// Indexes for header->e_ident[].
+enum e_ident_indexes {
+  EI_MAG0 = 0,        // File identification.
+  EI_MAG1 = 1,        // File identification.
+  EI_MAG2 = 2,        // File identification.
+  EI_MAG3 = 3,        // File identification.
+  EI_CLASS = 4,       // File class.
+  EI_DATA = 5,        // Data encoding.
+  EI_VERSION = 6,     // File version.
+  EI_OSABI = 7,       // Operating system/ABI identification.
+  EI_ABIVERSION = 8,  // ABI version.
+  EI_PAD = 9,         // Start of padding bytes.
+  EI_NIDENT = 16      // Size of e_ident[].
+};
+
+// Values for header->e_ident[EI_CLASS].
+enum e_ident_class_values {
+  ELFCLASSNONE = 0,  // Invalid class.
+  ELFCLASS32 = 1,    // 32-bit objects.
+  ELFCLASS64 = 2     // 64-bit objects.
+};
+
+// Values for header->e_ident[EI_DATA].
+enum e_ident_data_values {
+  ELFDATANONE = 0,  // Unknown data format.
+  ELFDATA2LSB = 1,  // Two's complement, little-endian.
+  ELFDATA2MSB = 2,  // Two's complement, big-endian.
+};
+
 // values for header->e_type
 enum e_type_values {
   ET_NONE = 0,  // No file type
@@ -56,6 +85,8 @@
   // Other values skipped
 };
 
+enum { SHN_UNDEF = 0 };
+
 // A section header in the section header table
 struct Elf32_Shdr {
   Elf32_Word   sh_name;
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 68e466e..42c9f05 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -403,7 +403,7 @@
       "//base:base_java",
       "//components/location/android:location_java",
       "//device/bluetooth:java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
       "//third_party/android_tools:android_test_mock_java",
     ]
 
@@ -421,7 +421,7 @@
       "//base:base_junit_test_support",
       "//device/gamepad:java",
       "//mojo/public/java:bindings_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
     srcjar_deps = [ "//device/gamepad:java_enums_srcjar" ]
   }
diff --git a/device/gamepad/BUILD.gn b/device/gamepad/BUILD.gn
index db70eff..759c76e 100644
--- a/device/gamepad/BUILD.gn
+++ b/device/gamepad/BUILD.gn
@@ -185,7 +185,7 @@
     ]
     deps = [
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
     srcjar_deps = [ ":java_enums_srcjar" ]
   }
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
index e6ede47..a5326123 100644
--- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
+++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
@@ -5,10 +5,12 @@
 #include "device/vr/windows_mixed_reality/mixed_reality_renderloop.h"
 
 #include <HolographicSpaceInterop.h>
+#include <SpatialInteractionManagerInterop.h>
 #include <Windows.Graphics.DirectX.Direct3D11.interop.h>
 #include <windows.graphics.holographic.h>
 #include <windows.perception.h>
 #include <windows.perception.spatial.h>
+#include <windows.ui.input.spatial.h>
 
 #include <algorithm>
 #include <utility>
@@ -28,6 +30,7 @@
 
 namespace device {
 
+// TODO(crbug.com/941546): Remove namespaces to comply with coding standard.
 using namespace ABI::Windows::Foundation;
 using namespace ABI::Windows::Graphics::Holographic;
 using namespace ABI::Windows::Perception;
@@ -35,6 +38,10 @@
 using namespace Microsoft::WRL;
 using namespace Microsoft::WRL::Wrappers;
 
+namespace WFC = ABI::Windows::Foundation::Collections;
+namespace WFN = ABI::Windows::Foundation::Numerics;
+namespace WInput = ABI::Windows::UI::Input::Spatial;
+
 class MixedRealityWindow : public gfx::WindowImpl {
   BOOL ProcessWindowMessage(HWND window,
                             UINT message,
@@ -100,6 +107,94 @@
   return field_of_view;
 }
 
+gfx::Transform CreateTransform(WFN::Vector3 position,
+                               WFN::Quaternion rotation) {
+  gfx::DecomposedTransform decomposed_transform;
+  decomposed_transform.translate[0] = position.X;
+  decomposed_transform.translate[1] = position.Y;
+  decomposed_transform.translate[2] = position.Z;
+
+  decomposed_transform.quaternion =
+      gfx::Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
+  return gfx::ComposeTransform(decomposed_transform);
+}
+
+bool TryGetGripFromLocation(
+    ComPtr<WInput::ISpatialInteractionSourceLocation> location_in_origin,
+    gfx::Transform* origin_from_grip) {
+  DCHECK(origin_from_grip);
+  *origin_from_grip = gfx::Transform();
+
+  if (!location_in_origin)
+    return false;
+
+  ComPtr<IReference<WFN::Vector3>> pos_ref;
+
+  if (FAILED(location_in_origin->get_Position(&pos_ref)) || !pos_ref)
+    return false;
+
+  WFN::Vector3 pos;
+  if (FAILED(pos_ref->get_Value(&pos)))
+    return false;
+
+  ComPtr<WInput::ISpatialInteractionSourceLocation2> location_in_origin2;
+  if (FAILED(location_in_origin.As(&location_in_origin2)))
+    return false;
+
+  ComPtr<IReference<WFN::Quaternion>> quat_ref;
+  if (FAILED(location_in_origin2->get_Orientation(&quat_ref)) || !quat_ref)
+    return false;
+
+  WFN::Quaternion quat;
+  if (FAILED(quat_ref->get_Value(&quat)))
+    return false;
+
+  *origin_from_grip = CreateTransform(pos, quat);
+  return true;
+}
+
+bool TryGetPointerOffsetFromLocation(
+    ComPtr<WInput::ISpatialInteractionSourceLocation> location_in_origin,
+    gfx::Transform origin_from_grip,
+    gfx::Transform* grip_from_pointer) {
+  DCHECK(grip_from_pointer);
+  *grip_from_pointer = gfx::Transform();
+
+  if (!location_in_origin)
+    return false;
+
+  // We can get the pointer position, but we'll need to transform it to an
+  // offset from the grip position.  If we can't get an inverse of that,
+  // then go ahead and bail early.
+  gfx::Transform grip_from_origin;
+  if (!origin_from_grip.GetInverse(&grip_from_origin))
+    return false;
+
+  ComPtr<WInput::ISpatialInteractionSourceLocation3> location_in_origin3;
+  if (FAILED(location_in_origin.As(&location_in_origin3)))
+    return false;
+
+  ComPtr<WInput::ISpatialPointerInteractionSourcePose> pointer_pose;
+  if (FAILED(location_in_origin3->get_SourcePointerPose(&pointer_pose)) ||
+      !pointer_pose)
+    return false;
+
+  WFN::Vector3 pos;
+  if (FAILED(pointer_pose->get_Position(&pos)))
+    return false;
+
+  ComPtr<WInput::ISpatialPointerInteractionSourcePose2> pose2;
+  if (FAILED(pointer_pose.As(&pose2)))
+    return false;
+
+  WFN::Quaternion rot;
+  if (FAILED(pose2->get_Orientation(&rot)))
+    return false;
+
+  gfx::Transform origin_from_pointer = CreateTransform(pos, rot);
+  *grip_from_pointer = (grip_from_origin * origin_from_pointer);
+  return true;
+}
 }  // namespace
 
 MixedRealityRenderLoop::MixedRealityRenderLoop(
@@ -232,7 +327,7 @@
   origin_ = nullptr;
 
   holographic_frame_ = nullptr;
-  prediction_ = nullptr;
+  timestamp_ = nullptr;
   poses_ = nullptr;
   pose_ = nullptr;
   rendering_params_ = nullptr;
@@ -436,12 +531,10 @@
 }
 
 mojom::XRFrameDataPtr CreateDefaultFrameData(
-    ComPtr<IHolographicFramePrediction> prediction,
+    ComPtr<IPerceptionTimestamp> timestamp,
     int16_t frame_id) {
   mojom::XRFrameDataPtr ret = mojom::XRFrameData::New();
 
-  ComPtr<IPerceptionTimestamp> timestamp;
-  prediction->get_Timestamp(&timestamp);
   ABI::Windows::Foundation::DateTime date_time;
   timestamp->get_TargetTime(&date_time);
 
@@ -465,22 +558,27 @@
 
 void MixedRealityRenderLoop::UpdateWMRDataForNextFrame() {
   holographic_frame_ = nullptr;
-  prediction_ = nullptr;
   poses_ = nullptr;
   pose_ = nullptr;
   rendering_params_ = nullptr;
   camera_ = nullptr;
+  timestamp_ = nullptr;
 
   // Start populating this frame's data.
   HRESULT hr = holographic_space_->CreateNextFrame(&holographic_frame_);
   if (FAILED(hr))
     return;
 
-  hr = holographic_frame_->get_CurrentPrediction(&prediction_);
+  ComPtr<IHolographicFramePrediction> prediction;
+  hr = holographic_frame_->get_CurrentPrediction(&prediction);
   if (FAILED(hr))
     return;
 
-  hr = prediction_->get_CameraPoses(&poses_);
+  hr = prediction->get_Timestamp(&timestamp_);
+  if (FAILED(hr))
+    return;
+
+  hr = prediction->get_CameraPoses(&poses_);
   if (FAILED(hr))
     return;
 
@@ -597,12 +695,12 @@
 
 mojom::XRFrameDataPtr MixedRealityRenderLoop::GetNextFrameData() {
   UpdateWMRDataForNextFrame();
-  if (!prediction_)
+  if (!timestamp_)
     return nullptr;
 
   // Once we have a prediction, we can generate a frame data.
   mojom::XRFrameDataPtr ret =
-      CreateDefaultFrameData(prediction_, next_frame_id_);
+      CreateDefaultFrameData(timestamp_, next_frame_id_);
 
   if (!origin_ || !pose_) {
     // If we don't have an origin or pose for this frame, we can still give out
@@ -666,6 +764,8 @@
                                   current_display_info_.Clone()));
   }
 
+  ret->pose->input_state = GetInputState();
+
   return ret;
 }
 
@@ -678,10 +778,146 @@
   return;
 }
 
+bool MixedRealityRenderLoop::EnsureSpatialInteractionManager() {
+  if (spatial_interaction_manager_)
+    return true;
+
+  if (!window_)
+    return false;
+
+  ComPtr<ISpatialInteractionManagerInterop> spatial_interaction_interop;
+  base::win::ScopedHString spatial_interaction_interop_string =
+      base::win::ScopedHString::Create(
+          RuntimeClass_Windows_UI_Input_Spatial_SpatialInteractionManager);
+  HRESULT hr = base::win::RoGetActivationFactory(
+      spatial_interaction_interop_string.get(),
+      IID_PPV_ARGS(&spatial_interaction_interop));
+  if (FAILED(hr))
+    return false;
+
+  hr = spatial_interaction_interop->GetForWindow(
+      window_->hwnd(), IID_PPV_ARGS(&spatial_interaction_manager_));
+  return SUCCEEDED(hr);
+}
+
 std::vector<mojom::XRInputSourceStatePtr>
 MixedRealityRenderLoop::GetInputState() {
-  // Not yet implemented.
-  return {};
+  std::vector<mojom::XRInputSourceStatePtr> input_states;
+
+  if (!timestamp_ || !origin_ || !EnsureSpatialInteractionManager())
+    return input_states;
+
+  ComPtr<WFC::IVectorView<WInput::SpatialInteractionSourceState*>>
+      source_states;
+  if (FAILED(spatial_interaction_manager_->GetDetectedSourcesAtTimestamp(
+          timestamp_.Get(), &source_states)))
+    return input_states;
+
+  unsigned int size;
+  if (FAILED(source_states->get_Size(&size)))
+    return input_states;
+
+  for (unsigned int i = 0; i < size; i++) {
+    ComPtr<WInput::ISpatialInteractionSourceState> state;
+    if (FAILED(source_states->GetAt(i, &state)))
+      continue;
+
+    // Get the source and query for all of the state that we send first
+    ComPtr<WInput::ISpatialInteractionSource> source;
+    if (FAILED(state->get_Source(&source)))
+      continue;
+
+    WInput::SpatialInteractionSourceKind source_kind;
+    if (FAILED(source->get_Kind(&source_kind)) ||
+        source_kind != WInput::SpatialInteractionSourceKind_Controller)
+      continue;
+
+    uint32_t id;
+    if (FAILED(source->get_Id(&id)))
+      continue;
+
+    ComPtr<WInput::ISpatialInteractionSourceState2> state2;
+    if (FAILED(state.As(&state2)))
+      continue;
+
+    boolean pressed = false;
+    if (FAILED(state2->get_IsSelectPressed(&pressed)))
+      continue;
+
+    ComPtr<WInput::ISpatialInteractionSourceProperties> props;
+    if (FAILED(state->get_Properties(&props)))
+      continue;
+
+    ComPtr<WInput::ISpatialInteractionSourceLocation> location_in_origin;
+    if (FAILED(props->TryGetLocation(origin_.Get(), &location_in_origin)) ||
+        !location_in_origin)
+      continue;
+
+    gfx::Transform origin_from_grip;
+    if (!TryGetGripFromLocation(location_in_origin, &origin_from_grip))
+      continue;
+
+    ComPtr<WInput::ISpatialInteractionSource2> source2;
+    boolean pointingSupported = false;
+    if (FAILED(source.As(&source2)) ||
+        FAILED(source2->get_IsPointingSupported(&pointingSupported)) ||
+        !pointingSupported)
+      continue;
+
+    gfx::Transform grip_from_pointer;
+    if (!TryGetPointerOffsetFromLocation(location_in_origin, origin_from_grip,
+                                         &grip_from_pointer))
+      continue;
+
+    // Now that we've queried for all of the state we're going to send,
+    // build the object to send it.
+    device::mojom::XRInputSourceStatePtr source_state =
+        device::mojom::XRInputSourceState::New();
+
+    // Hands may not have the same id especially if they are lost but since we
+    // are only tracking controllers, this id should be consistent.
+    source_state->source_id = id;
+
+    source_state->primary_input_pressed = pressed;
+    source_state->primary_input_clicked =
+        !pressed && controller_pressed_state_[id];
+    controller_pressed_state_[id] = pressed;
+
+    source_state->grip = origin_from_grip;
+
+    device::mojom::XRInputSourceDescriptionPtr description =
+        device::mojom::XRInputSourceDescription::New();
+
+    // It's a fully 6DoF handheld pointing device
+    description->emulated_position = false;
+    description->target_ray_mode = device::mojom::XRTargetRayMode::POINTING;
+
+    description->pointer_offset = grip_from_pointer;
+
+    WInput::SpatialInteractionSourceHandedness handedness;
+    ComPtr<WInput::ISpatialInteractionSource3> source3;
+    if (SUCCEEDED(source.As(&source3) &&
+                  SUCCEEDED(source3->get_Handedness(&handedness)))) {
+      switch (handedness) {
+        case WInput::SpatialInteractionSourceHandedness_Left:
+          description->handedness = device::mojom::XRHandedness::LEFT;
+          break;
+        case WInput::SpatialInteractionSourceHandedness_Right:
+          description->handedness = device::mojom::XRHandedness::RIGHT;
+          break;
+        default:
+          description->handedness = device::mojom::XRHandedness::NONE;
+          break;
+      }
+    } else {
+      description->handedness = device::mojom::XRHandedness::NONE;
+    }
+
+    source_state->description = std::move(description);
+    input_states.push_back(std::move(source_state));
+  }
+
+  return input_states;
 }
 
 }  // namespace device
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.h b/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
index 92f7ee6..1701003 100644
--- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
+++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
@@ -7,9 +7,12 @@
 
 #include <windows.graphics.holographic.h>
 #include <windows.perception.spatial.h>
+#include <windows.ui.input.spatial.h>
+
 #include <wrl.h>
 
 #include <memory>
+#include <unordered_map>
 #include <vector>
 
 #include "base/callback.h"
@@ -55,6 +58,7 @@
 
   // Helpers to implement XRDeviceAbstraction.
   std::vector<mojom::XRInputSourceStatePtr> GetInputState();
+  bool EnsureSpatialInteractionManager();
   void InitializeOrigin();
   void InitializeSpace();
   void StartPresenting();
@@ -76,9 +80,8 @@
   // Per frame data:
   Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Holographic::IHolographicFrame>
       holographic_frame_;
-  Microsoft::WRL::ComPtr<
-      ABI::Windows::Graphics::Holographic::IHolographicFramePrediction>
-      prediction_;
+  Microsoft::WRL::ComPtr<ABI::Windows::Perception::IPerceptionTimestamp>
+      timestamp_;
 
   // The set of all poses for this frame (there could be multiple headsets or
   // external cameras).
@@ -97,6 +100,12 @@
       ABI::Windows::Graphics::Holographic::IHolographicCamera>
       camera_;
 
+  // Input Data
+  Microsoft::WRL::ComPtr<
+      ABI::Windows::UI::Input::Spatial::ISpatialInteractionManager>
+      spatial_interaction_manager_;
+  std::unordered_map<uint32_t, bool> controller_pressed_state_;
+
   DISALLOW_COPY_AND_ASSIGN(MixedRealityRenderLoop);
 };
 
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 492e6f3..17cf3299 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -540,11 +540,14 @@
     "//base",
     "//content/public/browser",
     "//extensions/browser",
-    "//extensions/browser/api/declarative_net_request:test_support",
     "//extensions/common",
     "//extensions/common:test_support",
     "//testing/gtest",
   ]
+
+  public_deps = [
+    "//extensions/browser/api/declarative_net_request:test_support",
+  ]
 }
 
 source_set("unit_tests") {
@@ -559,6 +562,7 @@
     "api/declarative/declarative_rule_unittest.cc",
     "api/declarative/deduping_factory_unittest.cc",
     "api/declarative/rules_registry_unittest.cc",
+    "api/declarative_net_request/composite_matcher_unittest.cc",
     "api/declarative_net_request/flat_ruleset_indexer_unittest.cc",
     "api/declarative_net_request/indexed_rule_unittest.cc",
     "api/declarative_net_request/indexed_ruleset_format_version_unittest.cc",
diff --git a/extensions/browser/api/declarative_net_request/BUILD.gn b/extensions/browser/api/declarative_net_request/BUILD.gn
index a415211..ca30728b 100644
--- a/extensions/browser/api/declarative_net_request/BUILD.gn
+++ b/extensions/browser/api/declarative_net_request/BUILD.gn
@@ -4,6 +4,8 @@
 
 source_set("declarative_net_request") {
   sources = [
+    "composite_matcher.cc",
+    "composite_matcher.h",
     "constants.cc",
     "constants.h",
     "declarative_net_request_api.cc",
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.cc b/extensions/browser/api/declarative_net_request/composite_matcher.cc
new file mode 100644
index 0000000..cc236c0
--- /dev/null
+++ b/extensions/browser/api/declarative_net_request/composite_matcher.cc
@@ -0,0 +1,88 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
+
+#include <algorithm>
+#include <set>
+#include <utility>
+
+#include "base/metrics/histogram_macros.h"
+
+namespace extensions {
+namespace declarative_net_request {
+
+namespace {
+
+bool AreIDsUnique(const CompositeMatcher::MatcherList& matchers) {
+  std::set<size_t> ids;
+  for (const auto& matcher : matchers) {
+    bool did_insert = ids.insert(matcher->id()).second;
+    if (!did_insert)
+      return false;
+  }
+
+  return true;
+}
+
+bool AreSortedPrioritiesUnique(const CompositeMatcher::MatcherList& matchers) {
+  base::Optional<size_t> previous_priority;
+  for (const auto& matcher : matchers) {
+    if (matcher->priority() == previous_priority)
+      return false;
+    previous_priority = matcher->priority();
+  }
+
+  return true;
+}
+
+}  // namespace
+
+CompositeMatcher::CompositeMatcher(MatcherList matchers)
+    : matchers_(std::move(matchers)) {
+  // Sort in descending order of priority.
+  std::sort(matchers_.begin(), matchers_.end(),
+            [](const std::unique_ptr<RulesetMatcher>& a,
+               const std::unique_ptr<RulesetMatcher>& b) {
+              return a->priority() > b->priority();
+            });
+
+  DCHECK(AreIDsUnique(matchers_));
+  DCHECK(AreSortedPrioritiesUnique(matchers_));
+}
+
+CompositeMatcher::~CompositeMatcher() = default;
+
+bool CompositeMatcher::ShouldBlockRequest(const RequestParams& params) const {
+  // TODO(karandeepb): change this to report time in micro-seconds.
+  SCOPED_UMA_HISTOGRAM_TIMER(
+      "Extensions.DeclarativeNetRequest.ShouldBlockRequestTime."
+      "SingleExtension");
+
+  for (const auto& matcher : matchers_) {
+    if (matcher->HasMatchingAllowRule(params))
+      return false;
+    if (matcher->HasMatchingBlockRule(params))
+      return true;
+  }
+  return false;
+}
+
+bool CompositeMatcher::ShouldRedirectRequest(const RequestParams& params,
+                                             GURL* redirect_url) const {
+  // TODO(karandeepb): change this to report time in micro-seconds.
+  SCOPED_UMA_HISTOGRAM_TIMER(
+      "Extensions.DeclarativeNetRequest.ShouldRedirectRequestTime."
+      "SingleExtension");
+
+  for (const auto& matcher : matchers_) {
+    if (matcher->HasMatchingRedirectRule(params, redirect_url))
+      return true;
+  }
+
+  return false;
+}
+
+}  // namespace declarative_net_request
+}  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.h b/extensions/browser/api/declarative_net_request/composite_matcher.h
new file mode 100644
index 0000000..81362a1e
--- /dev/null
+++ b/extensions/browser/api/declarative_net_request/composite_matcher.h
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_COMPOSITE_MATCHER_H_
+#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_COMPOSITE_MATCHER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
+
+namespace extensions {
+namespace declarative_net_request {
+
+// Per extension instance which manages the different rulesets for an extension
+// while respecting their priorities.
+class CompositeMatcher {
+ public:
+  using MatcherList = std::vector<std::unique_ptr<RulesetMatcher>>;
+
+  // Each RulesetMatcher should have a distinct ID and priority.
+  explicit CompositeMatcher(MatcherList matchers);
+  ~CompositeMatcher();
+
+  // Returns whether the network request as specified by |params| should be
+  // blocked.
+  bool ShouldBlockRequest(const RequestParams& params) const;
+
+  // Returns whether the network request as specified by |params| should be
+  // redirected along with the |redirect_url|. |redirect_url| must not be null.
+  bool ShouldRedirectRequest(const RequestParams& params,
+                             GURL* redirect_url) const;
+
+ private:
+  // Sorted by priority in descending order.
+  MatcherList matchers_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompositeMatcher);
+};
+
+}  // namespace declarative_net_request
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_COMPOSITE_MATCHER_H_
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
new file mode 100644
index 0000000..beb7e42
--- /dev/null
+++ b/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "components/version_info/version_info.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
+#include "extensions/browser/api/declarative_net_request/test_utils.h"
+#include "extensions/common/api/declarative_net_request/constants.h"
+#include "extensions/common/api/declarative_net_request/test_utils.h"
+#include "extensions/common/features/feature_channel.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace extensions {
+namespace declarative_net_request {
+
+class CompositeMatcherTest : public ::testing::Test {
+ public:
+  CompositeMatcherTest() : channel_(::version_info::Channel::UNKNOWN) {}
+
+ private:
+  // Run this on the trunk channel to ensure the API is available.
+  ScopedCurrentChannel channel_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompositeMatcherTest);
+};
+
+// Ensure CompositeMatcher respects priority of individual rulesets.
+TEST_F(CompositeMatcherTest, RulesetPriority) {
+  TestRule block_rule = CreateGenericRule();
+  block_rule.condition->url_filter = std::string("google.com");
+  block_rule.id = kMinValidID;
+
+  TestRule redirect_rule_1 = CreateGenericRule();
+  redirect_rule_1.condition->url_filter = std::string("example.com");
+  redirect_rule_1.priority = kMinValidPriority;
+  redirect_rule_1.action->type = std::string("redirect");
+  redirect_rule_1.action->redirect_url = std::string("http://ruleset1.com");
+  redirect_rule_1.id = kMinValidID + 1;
+
+  // Create the first ruleset matcher.
+  const size_t kSource1ID = 1;
+  const size_t kSource1Priority = 1;
+  std::unique_ptr<RulesetMatcher> matcher_1;
+  ASSERT_TRUE(CreateVerifiedMatcher({block_rule, redirect_rule_1},
+                                    CreateTemporarySource(), &matcher_1));
+  matcher_1->set_id_for_testing(kSource1ID);
+  matcher_1->set_priority_for_testing(kSource1Priority);
+
+  // Now create a second ruleset matcher.
+  const size_t kSource2ID = 2;
+  const size_t kSource2Priority = 2;
+  TestRule allow_rule = block_rule;
+  allow_rule.action->type = std::string("allow");
+  TestRule redirect_rule_2 = redirect_rule_1;
+  redirect_rule_2.action->redirect_url = std::string("http://ruleset2.com");
+  std::unique_ptr<RulesetMatcher> matcher_2;
+  ASSERT_TRUE(CreateVerifiedMatcher({allow_rule, redirect_rule_2},
+                                    CreateTemporarySource(), &matcher_2));
+  matcher_2->set_id_for_testing(kSource2ID);
+  matcher_2->set_priority_for_testing(kSource2Priority);
+
+  // Create a composite matcher with the two rulesets.
+  std::vector<std::unique_ptr<RulesetMatcher>> matchers;
+  matchers.push_back(std::move(matcher_1));
+  matchers.push_back(std::move(matcher_2));
+  auto composite_matcher =
+      std::make_unique<CompositeMatcher>(std::move(matchers));
+
+  GURL google_url = GURL("http://google.com");
+  RequestParams google_params;
+  google_params.url = &google_url;
+  google_params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
+  google_params.is_third_party = false;
+
+  // The second ruleset should get more priority.
+  EXPECT_FALSE(composite_matcher->ShouldBlockRequest(google_params));
+
+  GURL example_url = GURL("http://example.com");
+  RequestParams example_params = google_params;
+  example_params.url = &example_url;
+  GURL redirect_url;
+  EXPECT_TRUE(
+      composite_matcher->ShouldRedirectRequest(example_params, &redirect_url));
+  EXPECT_EQ(GURL("http://ruleset2.com"), redirect_url);
+
+  // Now switch the priority of the two rulesets. This requires re-constructing
+  // the two ruleset matchers.
+  matcher_1.reset();
+  matcher_2.reset();
+  matchers.clear();
+  ASSERT_TRUE(CreateVerifiedMatcher({block_rule, redirect_rule_1},
+                                    CreateTemporarySource(), &matcher_1));
+  matcher_1->set_id_for_testing(kSource1ID);
+  matcher_1->set_priority_for_testing(kSource2Priority);
+  ASSERT_TRUE(CreateVerifiedMatcher({allow_rule, redirect_rule_2},
+                                    CreateTemporarySource(), &matcher_2));
+  matcher_2->set_id_for_testing(kSource2ID);
+  matcher_2->set_priority_for_testing(kSource1Priority);
+  matchers.push_back(std::move(matcher_1));
+  matchers.push_back(std::move(matcher_2));
+  composite_matcher = std::make_unique<CompositeMatcher>(std::move(matchers));
+
+  // The first ruleset should get more priority.
+  EXPECT_TRUE(composite_matcher->ShouldBlockRequest(google_params));
+  EXPECT_TRUE(
+      composite_matcher->ShouldRedirectRequest(example_params, &redirect_url));
+  EXPECT_EQ(GURL("http://ruleset1.com"), redirect_url);
+}
+
+}  // namespace declarative_net_request
+}  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
index 21485f8..72bfb7f 100644
--- a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
+++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -17,6 +17,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/service_manager_connection.h"
+#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_manager.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_source.h"
@@ -51,8 +52,14 @@
                            InfoMap* info_map) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(info_map);
+
+  // Only a single ruleset per extension is supported currently.
+  CompositeMatcher::MatcherList matchers;
+  matchers.push_back(std::move(ruleset_matcher));
+
   info_map->GetRulesetManager()->AddRuleset(
-      extension_id, std::move(ruleset_matcher), std::move(allowed_pages));
+      extension_id, std::make_unique<CompositeMatcher>(std::move(matchers)),
+      std::move(allowed_pages));
 }
 
 void UnloadRulesetOnIOThread(ExtensionId extension_id, InfoMap* info_map) {
@@ -110,7 +117,7 @@
     DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
 
     load_ruleset_result_ = RulesetMatcher::CreateVerifiedMatcher(
-        source_.indexed_path(), *expected_checksum_, &matcher_);
+        source_, *expected_checksum_, &matcher_);
 
     UMA_HISTOGRAM_ENUMERATION(
         "Extensions.DeclarativeNetRequest.LoadRulesetResult",
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
index f54f621..46cacc4 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_manager.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -18,14 +18,13 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_request_info.h"
-#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
+#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/web_request/web_request_info.h"
 #include "extensions/browser/api/web_request/web_request_permissions.h"
 #include "extensions/browser/info_map.h"
 #include "extensions/common/api/declarative_net_request/utils.h"
 #include "extensions/common/constants.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/origin.h"
 
 namespace extensions {
@@ -48,66 +47,6 @@
   kMaxValue = kBothCandidatesMatchInitiator,
 };
 
-// Maps content::ResourceType to flat_rule::ElementType.
-flat_rule::ElementType GetElementType(content::ResourceType type) {
-  switch (type) {
-    case content::RESOURCE_TYPE_LAST_TYPE:
-    case content::RESOURCE_TYPE_PREFETCH:
-    case content::RESOURCE_TYPE_SUB_RESOURCE:
-    case content::RESOURCE_TYPE_NAVIGATION_PRELOAD:
-      return flat_rule::ElementType_OTHER;
-    case content::RESOURCE_TYPE_MAIN_FRAME:
-      return flat_rule::ElementType_MAIN_FRAME;
-    case content::RESOURCE_TYPE_CSP_REPORT:
-      return flat_rule::ElementType_CSP_REPORT;
-    case content::RESOURCE_TYPE_SCRIPT:
-    case content::RESOURCE_TYPE_WORKER:
-    case content::RESOURCE_TYPE_SHARED_WORKER:
-    case content::RESOURCE_TYPE_SERVICE_WORKER:
-      return flat_rule::ElementType_SCRIPT;
-    case content::RESOURCE_TYPE_IMAGE:
-    case content::RESOURCE_TYPE_FAVICON:
-      return flat_rule::ElementType_IMAGE;
-    case content::RESOURCE_TYPE_STYLESHEET:
-      return flat_rule::ElementType_STYLESHEET;
-    case content::RESOURCE_TYPE_OBJECT:
-    case content::RESOURCE_TYPE_PLUGIN_RESOURCE:
-      return flat_rule::ElementType_OBJECT;
-    case content::RESOURCE_TYPE_XHR:
-      return flat_rule::ElementType_XMLHTTPREQUEST;
-    case content::RESOURCE_TYPE_SUB_FRAME:
-      return flat_rule::ElementType_SUBDOCUMENT;
-    case content::RESOURCE_TYPE_PING:
-      return flat_rule::ElementType_PING;
-    case content::RESOURCE_TYPE_MEDIA:
-      return flat_rule::ElementType_MEDIA;
-    case content::RESOURCE_TYPE_FONT_RESOURCE:
-      return flat_rule::ElementType_FONT;
-  }
-  NOTREACHED();
-  return flat_rule::ElementType_OTHER;
-}
-
-// Returns the flat_rule::ElementType for the given |request|.
-flat_rule::ElementType GetElementType(const WebRequestInfo& request) {
-  if (request.url.SchemeIsWSOrWSS())
-    return flat_rule::ElementType_WEBSOCKET;
-
-  return request.type.has_value() ? GetElementType(request.type.value())
-                                  : flat_rule::ElementType_OTHER;
-}
-
-// Returns whether the request to |url| is third party to its |document_origin|.
-// TODO(crbug.com/696822): Look into caching this.
-bool IsThirdPartyRequest(const GURL& url, const url::Origin& document_origin) {
-  if (document_origin.opaque())
-    return true;
-
-  return !net::registry_controlled_domains::SameDomainOrHost(
-      url, document_origin,
-      net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-}
-
 void ClearRendererCacheOnUI() {
   web_cache::WebCacheManager::GetInstance()->ClearCacheOnNavigation();
 }
@@ -264,7 +203,7 @@
 }
 
 void RulesetManager::AddRuleset(const ExtensionId& extension_id,
-                                std::unique_ptr<RulesetMatcher> ruleset_matcher,
+                                std::unique_ptr<CompositeMatcher> matcher,
                                 URLPatternSet allowed_pages) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsAPIAvailable());
@@ -272,7 +211,7 @@
   bool inserted;
   std::tie(std::ignore, inserted) =
       rulesets_.emplace(extension_id, info_map_->GetInstallTime(extension_id),
-                        std::move(ruleset_matcher), std::move(allowed_pages));
+                        std::move(matcher), std::move(allowed_pages));
   DCHECK(inserted) << "AddRuleset called twice in succession for "
                    << extension_id;
 
@@ -350,11 +289,7 @@
   SCOPED_UMA_HISTOGRAM_TIMER(
       "Extensions.DeclarativeNetRequest.EvaluateRequestTime.AllExtensions2");
 
-  const GURL& url = request.url;
-  const url::Origin first_party_origin =
-      request.initiator.value_or(url::Origin());
-  const flat_rule::ElementType element_type = GetElementType(request);
-  const bool is_third_party = IsThirdPartyRequest(url, first_party_origin);
+  RequestParams params(request);
   const int tab_id = request.frame_data ? request.frame_data->tab_id
                                         : extension_misc::kUnknownTabId;
 
@@ -388,10 +323,10 @@
       if (page_access != PageAccess::kAllowed)
         continue;
 
-      if (ruleset_data->matcher->ShouldBlockRequest(
-              url, first_party_origin, element_type, is_third_party)) {
-        return ShouldCollapseResourceType(element_type) ? Action::COLLAPSE
-                                                        : Action::BLOCK;
+      if (ruleset_data->matcher->ShouldBlockRequest(params)) {
+        return ShouldCollapseResourceType(params.element_type)
+                   ? Action::COLLAPSE
+                   : Action::BLOCK;
       }
     }
   }
@@ -400,7 +335,7 @@
   // redirect the request.
 
   // Redirecting WebSocket handshake request is prohibited.
-  if (element_type == flat_rule::ElementType_WEBSOCKET)
+  if (params.element_type == flat_rule::ElementType_WEBSOCKET)
     return Action::NONE;
 
   // This iterates in decreasing order of extension installation time. Hence
@@ -427,9 +362,7 @@
         continue;
       }
 
-      if (ruleset_data->matcher->ShouldRedirectRequest(
-              url, first_party_origin, element_type, is_third_party,
-              redirect_url)) {
+      if (ruleset_data->matcher->ShouldRedirectRequest(params, redirect_url)) {
         return Action::REDIRECT;
       }
     }
@@ -446,7 +379,7 @@
 RulesetManager::ExtensionRulesetData::ExtensionRulesetData(
     const ExtensionId& extension_id,
     const base::Time& extension_install_time,
-    std::unique_ptr<RulesetMatcher> matcher,
+    std::unique_ptr<CompositeMatcher> matcher,
     URLPatternSet allowed_pages)
     : extension_id(extension_id),
       extension_install_time(extension_install_time),
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.h b/extensions/browser/api/declarative_net_request/ruleset_manager.h
index 7deb96d..19c06a9 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_manager.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_manager.h
@@ -23,7 +23,7 @@
 struct WebRequestInfo;
 
 namespace declarative_net_request {
-class RulesetMatcher;
+class CompositeMatcher;
 
 // Manages the set of active rulesets for the Declarative Net Request API. Can
 // be constructed on any sequence but must be accessed and destroyed from the
@@ -59,7 +59,7 @@
   // Adds the ruleset for the given |extension_id|. Should not be called twice
   // in succession for an extension.
   void AddRuleset(const ExtensionId& extension_id,
-                  std::unique_ptr<RulesetMatcher> ruleset_matcher,
+                  std::unique_ptr<CompositeMatcher> matcher,
                   URLPatternSet allowed_pages);
 
   // Removes the ruleset for |extension_id|. Should be called only after a
@@ -78,7 +78,7 @@
                          bool is_incognito_context,
                          GURL* redirect_url) const;
 
-  // Returns the number of RulesetMatcher currently being managed.
+  // Returns the number of CompositeMatchers currently being managed.
   size_t GetMatcherCountForTest() const { return rulesets_.size(); }
 
   // Sets the TestObserver. Client maintains ownership of |observer|.
@@ -88,7 +88,7 @@
   struct ExtensionRulesetData {
     ExtensionRulesetData(const ExtensionId& extension_id,
                          const base::Time& extension_install_time,
-                         std::unique_ptr<RulesetMatcher> matcher,
+                         std::unique_ptr<CompositeMatcher> matcher,
                          URLPatternSet allowed_pages);
     ~ExtensionRulesetData();
     ExtensionRulesetData(ExtensionRulesetData&& other);
@@ -96,7 +96,7 @@
 
     ExtensionId extension_id;
     base::Time extension_install_time;
-    std::unique_ptr<RulesetMatcher> matcher;
+    std::unique_ptr<CompositeMatcher> matcher;
     URLPatternSet allowed_pages;
 
     bool operator<(const ExtensionRulesetData& other) const;
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
index 82ed7060..16ac956 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
@@ -12,10 +12,13 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/timer/elapsed_timer.h"
+#include "content/public/common/resource_type.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
+#include "extensions/browser/api/web_request/web_request_info.h"
 #include "extensions/common/api/declarative_net_request/utils.h"
-#include "url/gurl.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 
 namespace extensions {
 namespace declarative_net_request {
@@ -26,11 +29,84 @@
 using FindRuleStrategy =
     url_pattern_index::UrlPatternIndexMatcher::FindRuleStrategy;
 
+// Don't exclude generic rules from being matched. A generic rule is one with
+// an empty included domains list.
+const bool kDisableGenericRules = false;
+
+// Maps content::ResourceType to flat_rule::ElementType.
+flat_rule::ElementType GetElementType(content::ResourceType type) {
+  switch (type) {
+    case content::RESOURCE_TYPE_LAST_TYPE:
+    case content::RESOURCE_TYPE_PREFETCH:
+    case content::RESOURCE_TYPE_SUB_RESOURCE:
+    case content::RESOURCE_TYPE_NAVIGATION_PRELOAD:
+      return flat_rule::ElementType_OTHER;
+    case content::RESOURCE_TYPE_MAIN_FRAME:
+      return flat_rule::ElementType_MAIN_FRAME;
+    case content::RESOURCE_TYPE_CSP_REPORT:
+      return flat_rule::ElementType_CSP_REPORT;
+    case content::RESOURCE_TYPE_SCRIPT:
+    case content::RESOURCE_TYPE_WORKER:
+    case content::RESOURCE_TYPE_SHARED_WORKER:
+    case content::RESOURCE_TYPE_SERVICE_WORKER:
+      return flat_rule::ElementType_SCRIPT;
+    case content::RESOURCE_TYPE_IMAGE:
+    case content::RESOURCE_TYPE_FAVICON:
+      return flat_rule::ElementType_IMAGE;
+    case content::RESOURCE_TYPE_STYLESHEET:
+      return flat_rule::ElementType_STYLESHEET;
+    case content::RESOURCE_TYPE_OBJECT:
+    case content::RESOURCE_TYPE_PLUGIN_RESOURCE:
+      return flat_rule::ElementType_OBJECT;
+    case content::RESOURCE_TYPE_XHR:
+      return flat_rule::ElementType_XMLHTTPREQUEST;
+    case content::RESOURCE_TYPE_SUB_FRAME:
+      return flat_rule::ElementType_SUBDOCUMENT;
+    case content::RESOURCE_TYPE_PING:
+      return flat_rule::ElementType_PING;
+    case content::RESOURCE_TYPE_MEDIA:
+      return flat_rule::ElementType_MEDIA;
+    case content::RESOURCE_TYPE_FONT_RESOURCE:
+      return flat_rule::ElementType_FONT;
+  }
+  NOTREACHED();
+  return flat_rule::ElementType_OTHER;
+}
+
+// Returns the flat_rule::ElementType for the given |request|.
+flat_rule::ElementType GetElementType(const WebRequestInfo& request) {
+  if (request.url.SchemeIsWSOrWSS())
+    return flat_rule::ElementType_WEBSOCKET;
+
+  return request.type.has_value() ? GetElementType(request.type.value())
+                                  : flat_rule::ElementType_OTHER;
+}
+
+// Returns whether the request to |url| is third party to its |document_origin|.
+// TODO(crbug.com/696822): Look into caching this.
+bool IsThirdPartyRequest(const GURL& url, const url::Origin& document_origin) {
+  if (document_origin.opaque())
+    return true;
+
+  return !net::registry_controlled_domains::SameDomainOrHost(
+      url, document_origin,
+      net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+}
+
 }  // namespace
 
+RequestParams::RequestParams(const WebRequestInfo& info)
+    : url(&info.url),
+      first_party_origin(info.initiator.value_or(url::Origin())),
+      element_type(GetElementType(info)) {
+  is_third_party = IsThirdPartyRequest(*url, first_party_origin);
+}
+
+RequestParams::RequestParams() = default;
+
 // static
 RulesetMatcher::LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher(
-    const base::FilePath& indexed_ruleset_path,
+    const RulesetSource& source,
     int expected_ruleset_checksum,
     std::unique_ptr<RulesetMatcher>* matcher) {
   DCHECK(matcher);
@@ -38,11 +114,11 @@
 
   base::ElapsedTimer timer;
 
-  if (!base::PathExists(indexed_ruleset_path))
+  if (!base::PathExists(source.indexed_path()))
     return kLoadErrorInvalidPath;
 
   std::string ruleset_data;
-  if (!base::ReadFileToString(indexed_ruleset_path, &ruleset_data))
+  if (!base::ReadFileToString(source.indexed_path(), &ruleset_data))
     return kLoadErrorFileRead;
 
   if (!StripVersionHeaderAndParseVersion(&ruleset_data))
@@ -62,57 +138,41 @@
 
   // Using WrapUnique instead of make_unique since this class has a private
   // constructor.
-  *matcher = base::WrapUnique(new RulesetMatcher(std::move(ruleset_data)));
+  *matcher = base::WrapUnique(new RulesetMatcher(
+      std::move(ruleset_data), source.id(), source.priority()));
   return kLoadSuccess;
 }
 
 RulesetMatcher::~RulesetMatcher() = default;
 
-bool RulesetMatcher::ShouldBlockRequest(const GURL& url,
-                                        const url::Origin& first_party_origin,
-                                        flat_rule::ElementType element_type,
-                                        bool is_third_party) const {
-  SCOPED_UMA_HISTOGRAM_TIMER(
-      "Extensions.DeclarativeNetRequest.ShouldBlockRequestTime."
-      "SingleExtension");
-
-  // Don't exclude generic rules from being matched. A generic rule is one with
-  // an empty included domains list.
-  const bool disable_generic_rules = false;
-
-  bool success =
-      !!blocking_matcher_.FindMatch(
-          url, first_party_origin, element_type, flat_rule::ActivationType_NONE,
-          is_third_party, disable_generic_rules, FindRuleStrategy::kAny) &&
-      !allowing_matcher_.FindMatch(
-          url, first_party_origin, element_type, flat_rule::ActivationType_NONE,
-          is_third_party, disable_generic_rules, FindRuleStrategy::kAny);
-  return success;
+bool RulesetMatcher::HasMatchingBlockRule(const RequestParams& params) const {
+  DCHECK(params.url);
+  return blocking_matcher_.FindMatch(
+      *params.url, params.first_party_origin, params.element_type,
+      flat_rule::ActivationType_NONE, params.is_third_party,
+      kDisableGenericRules, FindRuleStrategy::kAny);
 }
 
-bool RulesetMatcher::ShouldRedirectRequest(
-    const GURL& url,
-    const url::Origin& first_party_origin,
-    flat_rule::ElementType element_type,
-    bool is_third_party,
-    GURL* redirect_url) const {
+bool RulesetMatcher::HasMatchingAllowRule(const RequestParams& params) const {
+  DCHECK(params.url);
+  return allowing_matcher_.FindMatch(
+      *params.url, params.first_party_origin, params.element_type,
+      flat_rule::ActivationType_NONE, params.is_third_party,
+      kDisableGenericRules, FindRuleStrategy::kAny);
+}
+
+bool RulesetMatcher::HasMatchingRedirectRule(const RequestParams& params,
+                                             GURL* redirect_url) const {
   DCHECK(redirect_url);
-  DCHECK_NE(flat_rule::ElementType_WEBSOCKET, element_type);
-
-  SCOPED_UMA_HISTOGRAM_TIMER(
-      "Extensions.DeclarativeNetRequest.ShouldRedirectRequestTime."
-      "SingleExtension");
-
-  // Don't exclude generic rules from being matched. A generic rule is one with
-  // an empty included domains list.
-  const bool disable_generic_rules = false;
+  DCHECK(params.url);
+  DCHECK_NE(flat_rule::ElementType_WEBSOCKET, params.element_type);
 
   // Retrieve the highest priority matching rule corresponding to the given
   // request parameters.
   const flat_rule::UrlRule* rule = redirect_matcher_.FindMatch(
-      url, first_party_origin, element_type, flat_rule::ActivationType_NONE,
-      is_third_party, disable_generic_rules,
-      FindRuleStrategy::kHighestPriority);
+      *params.url, params.first_party_origin, params.element_type,
+      flat_rule::ActivationType_NONE, params.is_third_party,
+      kDisableGenericRules, FindRuleStrategy::kHighestPriority);
   if (!rule)
     return false;
 
@@ -131,13 +191,17 @@
   return true;
 }
 
-RulesetMatcher::RulesetMatcher(std::string ruleset_data)
+RulesetMatcher::RulesetMatcher(std::string ruleset_data,
+                               size_t id,
+                               size_t priority)
     : ruleset_data_(std::move(ruleset_data)),
       root_(flat::GetExtensionIndexedRuleset(ruleset_data_.data())),
       blocking_matcher_(root_->blocking_index()),
       allowing_matcher_(root_->allowing_index()),
       redirect_matcher_(root_->redirect_index()),
-      metadata_list_(root_->extension_metadata()) {}
+      metadata_list_(root_->extension_metadata()),
+      id_(id),
+      priority_(priority) {}
 
 }  // namespace declarative_net_request
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.h b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
index 76876a2..cc959f0 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
@@ -9,27 +9,35 @@
 #include <string>
 
 #include "components/url_pattern_index/url_pattern_index.h"
-
-namespace base {
-class FilePath;
-}  // namespace base
-
-class GURL;
-
-namespace url {
-class Origin;
-}  // namespace url
+#include "url/gurl.h"
+#include "url/origin.h"
 
 namespace extensions {
+struct WebRequestInfo;
+
 namespace declarative_net_request {
+class RulesetSource;
 
 namespace flat {
 struct ExtensionIndexedRuleset;
 struct UrlRuleMetadata;
 }  // namespace flat
 
+// Struct to hold parameters for a network request.
+struct RequestParams {
+  // |info| must outlive this instance.
+  explicit RequestParams(const WebRequestInfo& info);
+  RequestParams();
+
+  // This is a pointer to a GURL. Hence the GURL must outlive this struct.
+  const GURL* url = nullptr;
+  url::Origin first_party_origin;
+  url_pattern_index::flat::ElementType element_type;
+  bool is_third_party;
+};
+
 // RulesetMatcher encapsulates the Declarative Net Request API ruleset
-// corresponding to a single extension. This uses the url_pattern_index
+// corresponding to a single RulesetSource. This uses the url_pattern_index
 // component to achieve fast matching of network requests against declarative
 // rules. Since this class is immutable, it is thread-safe. In practice it is
 // accessed on the IO thread but created on a sequence where file IO is allowed.
@@ -57,39 +65,44 @@
     kLoadResultMax
   };
 
-  // Factory function to create a verified RulesetMatcher.
-  // |indexed_ruleset_path| is the path of the extension ruleset in flatbuffer
-  // format. Must be called on a sequence where file IO is allowed. Returns
-  // kLoadSuccess on success along with the ruleset |matcher|.
+  // Factory function to create a verified RulesetMatcher for |source|. Must be
+  // called on a sequence where file IO is allowed. Returns kLoadSuccess on
+  // success along with the ruleset |matcher|.
   static LoadRulesetResult CreateVerifiedMatcher(
-      const base::FilePath& indexed_ruleset_path,
+      const RulesetSource& source,
       int expected_ruleset_checksum,
       std::unique_ptr<RulesetMatcher>* matcher);
 
   ~RulesetMatcher();
 
-  // Returns whether the network request as specified by the passed parameters
-  // should be blocked.
-  bool ShouldBlockRequest(const GURL& url,
-                          const url::Origin& first_party_origin,
-                          url_pattern_index::flat::ElementType element_type,
-                          bool is_third_party) const;
+  // Returns whether the ruleset has a matching blocking rule.
+  bool HasMatchingBlockRule(const RequestParams& params) const;
 
-  // Returns whether the network request as specified by the passed parameters
-  // should be redirected along with the |redirect_url|. |redirect_url| must
-  // not be null.
-  bool ShouldRedirectRequest(const GURL& url,
-                             const url::Origin& first_party_origin,
-                             url_pattern_index::flat::ElementType element_type,
-                             bool is_third_party,
-                             GURL* redirect_url) const;
+  // Returns whether the ruleset has a matching allow rule.
+  bool HasMatchingAllowRule(const RequestParams& params) const;
+
+  // Returns whether the ruleset has a matching redirect rule. Populates
+  // |redirect_url| on returning true. |redirect_url| must not be null.
+  bool HasMatchingRedirectRule(const RequestParams& params,
+                               GURL* redirect_url) const;
+
+  // ID of the ruleset. Each extension can have multiple rulesets with
+  // their own unique ids.
+  size_t id() const { return id_; }
+
+  // Priority of the ruleset. Each extension can have multiple rulesets with
+  // their own different priorities.
+  size_t priority() const { return priority_; }
+
+  void set_id_for_testing(size_t id) { id_ = id; }
+  void set_priority_for_testing(size_t priority) { priority_ = priority; }
 
  private:
   using UrlPatternIndexMatcher = url_pattern_index::UrlPatternIndexMatcher;
   using ExtensionMetadataList =
       flatbuffers::Vector<flatbuffers::Offset<flat::UrlRuleMetadata>>;
 
-  explicit RulesetMatcher(std::string ruleset_data);
+  explicit RulesetMatcher(std::string ruleset_data, size_t id, size_t priority);
 
   const std::string ruleset_data_;
 
@@ -99,6 +112,9 @@
   const UrlPatternIndexMatcher redirect_matcher_;
   const ExtensionMetadataList* const metadata_list_;
 
+  size_t id_;
+  size_t priority_;
+
   DISALLOW_COPY_AND_ASSIGN(RulesetMatcher);
 };
 
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
index 0a0c958a..0a92a9a 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
@@ -7,18 +7,16 @@
 #include <utility>
 #include <vector>
 
-#include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
 #include "components/url_pattern_index/flat/url_pattern_index_generated.h"
 #include "components/version_info/version_info.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_source.h"
+#include "extensions/browser/api/declarative_net_request/test_utils.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
 #include "extensions/common/api/declarative_net_request/constants.h"
 #include "extensions/common/api/declarative_net_request/test_utils.h"
 #include "extensions/common/features/feature_channel.h"
-#include "extensions/common/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -31,42 +29,6 @@
  public:
   RulesetMatcherTest() : channel_(::version_info::Channel::UNKNOWN) {}
 
- protected:
-  // Helper to create a verified ruleset matcher. Populates |matcher| and
-  // |expected_checksum|.
-  void CreateVerifiedMatcher(const std::vector<TestRule>& rules,
-                             const RulesetSource& source,
-                             std::unique_ptr<RulesetMatcher>* matcher,
-                             int* expected_checksum = nullptr) {
-    // Serialize |rules|.
-    ListBuilder builder;
-    for (const auto& rule : rules)
-      builder.Append(rule.ToValue());
-    JSONFileValueSerializer(source.json_path()).Serialize(*builder.Build());
-
-    // Index ruleset.
-    IndexAndPersistRulesResult result = source.IndexAndPersistRulesUnsafe();
-    ASSERT_TRUE(result.success);
-    ASSERT_TRUE(result.error.empty());
-
-    if (expected_checksum)
-      *expected_checksum = result.ruleset_checksum;
-
-    // Create verified matcher.
-    RulesetMatcher::LoadRulesetResult load_result =
-        RulesetMatcher::CreateVerifiedMatcher(source.indexed_path(),
-                                              result.ruleset_checksum, matcher);
-    ASSERT_EQ(RulesetMatcher::kLoadSuccess, load_result);
-  }
-
-  RulesetSource CreateTemporarySource() {
-    base::FilePath json_path;
-    base::FilePath indexed_path;
-    CHECK(base::CreateTemporaryFile(&json_path));
-    CHECK(base::CreateTemporaryFile(&indexed_path));
-    return RulesetSource(std::move(json_path), std::move(indexed_path));
-  }
-
  private:
   // Run this on the trunk channel to ensure the API is available.
   ScopedCurrentChannel channel_;
@@ -75,24 +37,33 @@
 };
 
 // Tests a simple blocking rule.
-TEST_F(RulesetMatcherTest, ShouldBlockRequest) {
+TEST_F(RulesetMatcherTest, BlockingRule) {
   TestRule rule = CreateGenericRule();
   rule.condition->url_filter = std::string("google.com");
 
   std::unique_ptr<RulesetMatcher> matcher;
-  ASSERT_NO_FATAL_FAILURE(
-      CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
+  ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
 
-  EXPECT_TRUE(matcher->ShouldBlockRequest(
-      GURL("http://google.com"), url::Origin(),
-      url_pattern_index::flat::ElementType_SUBDOCUMENT, true));
-  EXPECT_FALSE(matcher->ShouldBlockRequest(
-      GURL("http://yahoo.com"), url::Origin(),
-      url_pattern_index::flat::ElementType_SUBDOCUMENT, true));
+  auto should_block_request = [&matcher](const RequestParams& params) {
+    return !matcher->HasMatchingAllowRule(params) &&
+           matcher->HasMatchingBlockRule(params);
+  };
+
+  GURL google_url("http://google.com");
+  RequestParams params;
+  params.url = &google_url;
+  params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
+  params.is_third_party = true;
+
+  EXPECT_TRUE(should_block_request(params));
+
+  GURL yahoo_url("http://yahoo.com");
+  params.url = &yahoo_url;
+  EXPECT_FALSE(should_block_request(params));
 }
 
 // Tests a simple redirect rule.
-TEST_F(RulesetMatcherTest, ShouldRedirectRequest) {
+TEST_F(RulesetMatcherTest, RedirectRule) {
   TestRule rule = CreateGenericRule();
   rule.condition->url_filter = std::string("google.com");
   rule.priority = kMinValidPriority;
@@ -100,18 +71,27 @@
   rule.action->redirect_url = std::string("http://yahoo.com");
 
   std::unique_ptr<RulesetMatcher> matcher;
-  ASSERT_NO_FATAL_FAILURE(
-      CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
+  ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
+
+  auto should_redirect_request = [&matcher](const RequestParams& params,
+                                            GURL* redirect_url) {
+    return matcher->HasMatchingRedirectRule(params, redirect_url);
+  };
+
+  GURL google_url("http://google.com");
+  GURL yahoo_url("http://yahoo.com");
+
+  RequestParams params;
+  params.url = &google_url;
+  params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
+  params.is_third_party = true;
 
   GURL redirect_url;
-  EXPECT_TRUE(matcher->ShouldRedirectRequest(
-      GURL("http://google.com"), url::Origin(),
-      url_pattern_index::flat::ElementType_SUBDOCUMENT, true, &redirect_url));
-  EXPECT_EQ(GURL("http://yahoo.com"), redirect_url);
+  EXPECT_TRUE(should_redirect_request(params, &redirect_url));
+  EXPECT_EQ(yahoo_url, redirect_url);
 
-  EXPECT_FALSE(matcher->ShouldRedirectRequest(
-      GURL("http://yahoo.com"), url::Origin(),
-      url_pattern_index::flat::ElementType_SUBDOCUMENT, true, &redirect_url));
+  params.url = &yahoo_url;
+  EXPECT_FALSE(should_redirect_request(params, &redirect_url));
 }
 
 // Tests that a modified ruleset file fails verification.
@@ -119,8 +99,7 @@
   RulesetSource source = CreateTemporarySource();
   std::unique_ptr<RulesetMatcher> matcher;
   int expected_checksum;
-  ASSERT_NO_FATAL_FAILURE(
-      CreateVerifiedMatcher({}, source, &matcher, &expected_checksum));
+  ASSERT_TRUE(CreateVerifiedMatcher({}, source, &matcher, &expected_checksum));
 
   // Persist invalid data to the ruleset file and ensure that a version mismatch
   // occurs.
@@ -128,8 +107,8 @@
   ASSERT_EQ(static_cast<int>(data.size()),
             base::WriteFile(source.indexed_path(), data.c_str(), data.size()));
   EXPECT_EQ(RulesetMatcher::kLoadErrorVersionMismatch,
-            RulesetMatcher::CreateVerifiedMatcher(source.indexed_path(),
-                                                  expected_checksum, &matcher));
+            RulesetMatcher::CreateVerifiedMatcher(source, expected_checksum,
+                                                  &matcher));
 
   // Now, persist invalid data to the ruleset file, while maintaining the
   // correct version header. Ensure that it fails verification due to checksum
@@ -138,8 +117,8 @@
   ASSERT_EQ(static_cast<int>(data.size()),
             base::WriteFile(source.indexed_path(), data.c_str(), data.size()));
   EXPECT_EQ(RulesetMatcher::kLoadErrorChecksumMismatch,
-            RulesetMatcher::CreateVerifiedMatcher(source.indexed_path(),
-                                                  expected_checksum, &matcher));
+            RulesetMatcher::CreateVerifiedMatcher(source, expected_checksum,
+                                                  &matcher));
 }
 
 }  // namespace
diff --git a/extensions/browser/api/declarative_net_request/ruleset_source.cc b/extensions/browser/api/declarative_net_request/ruleset_source.cc
index 04cb0f8..a955b034 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_source.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_source.cc
@@ -43,6 +43,11 @@
 
 namespace dnr_api = extensions::api::declarative_net_request;
 
+// TODO(crbug.com/930961): Change once multiple rulesets within an extension are
+// supported.
+const size_t kDefaultRulesetID = 0;
+const size_t kDefaultRulesetPriority = 0;
+
 // Helper to retrieve the filename for the given |file_path|.
 std::string GetFilename(const base::FilePath& file_path) {
   return file_path.BaseName().AsUTF8Unsafe();
@@ -225,7 +230,9 @@
 RulesetSource::RulesetSource(base::FilePath json_path,
                              base::FilePath indexed_path)
     : json_path_(std::move(json_path)),
-      indexed_path_(std::move(indexed_path)) {}
+      indexed_path_(std::move(indexed_path)),
+      id_(kDefaultRulesetID),
+      priority_(kDefaultRulesetPriority) {}
 
 RulesetSource::~RulesetSource() = default;
 RulesetSource::RulesetSource(RulesetSource&&) = default;
diff --git a/extensions/browser/api/declarative_net_request/ruleset_source.h b/extensions/browser/api/declarative_net_request/ruleset_source.h
index aad63c11..2a3814e 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_source.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_source.h
@@ -73,6 +73,10 @@
   // Path to the indexed flatbuffer rules.
   const base::FilePath& indexed_path() const { return indexed_path_; }
 
+  // Each ruleset source within an extension has a distinct ID and priority.
+  size_t id() const { return id_; }
+  size_t priority() const { return priority_; }
+
   // Indexes and persists the JSON ruleset. This is potentially unsafe since the
   // JSON rules file is parsed in-process. Note: This must be called on a
   // sequence where file IO is allowed.
@@ -94,6 +98,8 @@
  private:
   base::FilePath json_path_;
   base::FilePath indexed_path_;
+  size_t id_;
+  size_t priority_;
 
   DISALLOW_COPY_AND_ASSIGN(RulesetSource);
 };
diff --git a/extensions/browser/api/declarative_net_request/test_utils.cc b/extensions/browser/api/declarative_net_request/test_utils.cc
index 6347c79..185337b0 100644
--- a/extensions/browser/api/declarative_net_request/test_utils.cc
+++ b/extensions/browser/api/declarative_net_request/test_utils.cc
@@ -5,11 +5,18 @@
 #include "extensions/browser/api/declarative_net_request/test_utils.h"
 
 #include <string>
+#include <utility>
 
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/logging.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/common/api/declarative_net_request/test_utils.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/file_util.h"
+#include "extensions/common/value_builder.h"
 
 namespace extensions {
 namespace declarative_net_request {
@@ -23,9 +30,44 @@
   }
 
   std::unique_ptr<RulesetMatcher> matcher;
-  return RulesetMatcher::CreateVerifiedMatcher(
-             file_util::GetIndexedRulesetPath(extension.path()),
-             expected_checksum, &matcher) == RulesetMatcher::kLoadSuccess;
+  return RulesetMatcher::CreateVerifiedMatcher(RulesetSource::Create(extension),
+                                               expected_checksum, &matcher) ==
+         RulesetMatcher::kLoadSuccess;
+}
+
+bool CreateVerifiedMatcher(const std::vector<TestRule>& rules,
+                           const RulesetSource& source,
+                           std::unique_ptr<RulesetMatcher>* matcher,
+                           int* expected_checksum) {
+  // Serialize |rules|.
+  ListBuilder builder;
+  for (const auto& rule : rules)
+    builder.Append(rule.ToValue());
+  JSONFileValueSerializer(source.json_path()).Serialize(*builder.Build());
+
+  // Index ruleset.
+  IndexAndPersistRulesResult result = source.IndexAndPersistRulesUnsafe();
+  if (!result.success) {
+    DCHECK(result.error.empty());
+    return false;
+  }
+
+  if (expected_checksum)
+    *expected_checksum = result.ruleset_checksum;
+
+  // Create verified matcher.
+  RulesetMatcher::LoadRulesetResult load_result =
+      RulesetMatcher::CreateVerifiedMatcher(source, result.ruleset_checksum,
+                                            matcher);
+  return load_result == RulesetMatcher::kLoadSuccess;
+}
+
+RulesetSource CreateTemporarySource() {
+  base::FilePath json_path;
+  base::FilePath indexed_path;
+  CHECK(base::CreateTemporaryFile(&json_path));
+  CHECK(base::CreateTemporaryFile(&indexed_path));
+  return RulesetSource(std::move(json_path), std::move(indexed_path));
 }
 
 }  // namespace declarative_net_request
diff --git a/extensions/browser/api/declarative_net_request/test_utils.h b/extensions/browser/api/declarative_net_request/test_utils.h
index eeb9c87..1268ce36b 100644
--- a/extensions/browser/api/declarative_net_request/test_utils.h
+++ b/extensions/browser/api/declarative_net_request/test_utils.h
@@ -5,6 +5,9 @@
 #ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
 #define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
 
+#include <memory>
+#include <vector>
+
 namespace content {
 class BrowserContext;
 }  // namespace content
@@ -14,6 +17,9 @@
 class Extension;
 
 namespace declarative_net_request {
+class RulesetSource;
+class RulesetMatcher;
+struct TestRule;
 
 // Enum specifying the extension load type. Used for parameterized tests.
 enum class ExtensionLoadType {
@@ -26,6 +32,16 @@
 bool HasValidIndexedRuleset(const Extension& extension,
                             content::BrowserContext* browser_context);
 
+// Helper to create a verified ruleset matcher. Populates |matcher| and
+// |expected_checksum|. Returns true on success.
+bool CreateVerifiedMatcher(const std::vector<TestRule>& rules,
+                           const RulesetSource& source,
+                           std::unique_ptr<RulesetMatcher>* matcher,
+                           int* expected_checksum = nullptr);
+
+// Helper to return a RulesetSource bound to temporary files.
+RulesetSource CreateTemporarySource();
+
 }  // namespace declarative_net_request
 }  // namespace extensions
 
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
index 597da59..04ec5ca4 100644
--- a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
+++ b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
@@ -13,7 +13,7 @@
 #include "base/lazy_instance.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/media_analytics_client.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/media_perception_private/conversion_utils.h"
 #include "extensions/browser/api/media_perception_private/media_perception_api_delegate.h"
@@ -146,9 +146,7 @@
 
 MediaPerceptionAPIManager::~MediaPerceptionAPIManager() {
   // Stop the separate media analytics process.
-  chromeos::UpstartClient* upstart_client =
-      chromeos::DBusThreadManager::Get()->GetUpstartClient();
-  upstart_client->StopMediaAnalytics();
+  chromeos::UpstartClient::Get()->StopMediaAnalytics();
 }
 
 void MediaPerceptionAPIManager::ActivateMediaPerception(
@@ -243,12 +241,11 @@
   analytics_process_state_ = AnalyticsProcessState::CHANGING_PROCESS_STATE;
   if (process_state.status ==
       extensions::api::media_perception_private::PROCESS_STATUS_STOPPED) {
-    chromeos::UpstartClient* dbus_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
     base::OnceCallback<void(bool)> stop_callback =
         base::BindOnce(&MediaPerceptionAPIManager::UpstartStopProcessCallback,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback));
-    dbus_client->StopMediaAnalytics(std::move(stop_callback));
+    chromeos::UpstartClient::Get()->StopMediaAnalytics(
+        std::move(stop_callback));
     return;
   }
 
@@ -264,12 +261,10 @@
       return;
     }
 
-    chromeos::UpstartClient* dbus_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
     std::vector<std::string> upstart_env;
     upstart_env.push_back(std::string("mount_point=") + mount_point_);
 
-    dbus_client->StartMediaAnalytics(
+    chromeos::UpstartClient::Get()->StartMediaAnalytics(
         upstart_env,
         base::BindOnce(&MediaPerceptionAPIManager::UpstartStartProcessCallback,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -305,9 +300,7 @@
   // upstart stop command if requested.
   if (state_proto.status() == mri::State::STOPPED) {
     analytics_process_state_ = AnalyticsProcessState::CHANGING_PROCESS_STATE;
-    chromeos::UpstartClient* dbus_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
-    dbus_client->StopMediaAnalytics(
+    chromeos::UpstartClient::Get()->StopMediaAnalytics(
         base::BindOnce(&MediaPerceptionAPIManager::UpstartStopCallback,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
     return;
@@ -317,9 +310,7 @@
   // then send restart upstart command.
   if (state_proto.status() == mri::State::RESTARTING) {
     analytics_process_state_ = AnalyticsProcessState::CHANGING_PROCESS_STATE;
-    chromeos::UpstartClient* dbus_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
-    dbus_client->RestartMediaAnalytics(
+    chromeos::UpstartClient::Get()->RestartMediaAnalytics(
         base::BindOnce(&MediaPerceptionAPIManager::UpstartRestartCallback,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
     return;
@@ -333,8 +324,6 @@
   // Analytics process is in state IDLE.
   if (state_proto.status() == mri::State::RUNNING) {
     analytics_process_state_ = AnalyticsProcessState::CHANGING_PROCESS_STATE;
-    chromeos::UpstartClient* dbus_client =
-        chromeos::DBusThreadManager::Get()->GetUpstartClient();
     std::vector<std::string> upstart_env;
     // Check if a component is loaded and add the necessary mount_point
     // information to the Upstart start command. If no component is loaded,
@@ -347,7 +336,7 @@
     if (!mount_point_.empty())
       upstart_env.push_back(std::string("mount_point=") + mount_point_);
 
-    dbus_client->StartMediaAnalytics(
+    chromeos::UpstartClient::Get()->StartMediaAnalytics(
         upstart_env,
         base::BindOnce(&MediaPerceptionAPIManager::UpstartStartCallback,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback),
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc b/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc
index 30dc97d..636b44b 100644
--- a/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc
+++ b/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc
@@ -4,14 +4,15 @@
 
 #include "extensions/browser/api/media_perception_private/media_perception_api_manager.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/containers/queue.h"
 #include "base/run_loop.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_media_analytics_client.h"
-#include "chromeos/dbus/fake_upstart_client.h"
 #include "chromeos/dbus/media_analytics_client.h"
-#include "chromeos/dbus/upstart_client.h"
+#include "chromeos/dbus/upstart/fake_upstart_client.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -156,7 +157,8 @@
 
 class MediaPerceptionAPIManagerTest : public testing::Test {
  public:
-  MediaPerceptionAPIManagerTest() {}
+  MediaPerceptionAPIManagerTest() = default;
+  ~MediaPerceptionAPIManagerTest() override = default;
 
   void SetUp() override {
     std::unique_ptr<chromeos::DBusThreadManagerSetter> dbus_setter =
@@ -166,9 +168,7 @@
     media_analytics_client_ = media_analytics_client.get();
     dbus_setter->SetMediaAnalyticsClient(std::move(media_analytics_client));
 
-    auto upstart_client = std::make_unique<TestUpstartClient>();
-    upstart_client_ = upstart_client.get();
-    dbus_setter->SetUpstartClient(std::move(upstart_client));
+    upstart_client_ = std::make_unique<TestUpstartClient>();
 
     manager_ = std::make_unique<MediaPerceptionAPIManager>(&browser_context_);
     manager_->SetMountPointNonEmptyForTesting();
@@ -178,6 +178,7 @@
     // Need to make sure that the MediaPerceptionAPIManager is destructed before
     // the DbusThreadManager.
     manager_.reset();
+    upstart_client_.reset();
     chromeos::DBusThreadManager::Shutdown();
   }
 
@@ -185,17 +186,18 @@
 
   // Ownership of both is passed on to chromeos::DbusThreadManager.
   chromeos::FakeMediaAnalyticsClient* media_analytics_client_;
-  TestUpstartClient* upstart_client_;
+  TestUpstartClient* upstart_client() { return upstart_client_.get(); }
 
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   content::TestBrowserContext browser_context_;
+  std::unique_ptr<TestUpstartClient> upstart_client_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaPerceptionAPIManagerTest);
 };
 
 TEST_F(MediaPerceptionAPIManagerTest, UpstartFailure) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::State state;
   state.status = media_perception::STATUS_RUNNING;
 
@@ -204,18 +206,18 @@
   manager_->SetState(state,
                      base::Bind(&RecordServiceErrorFromStateAndRunClosure,
                                 run_loop.QuitClosure(), &service_error));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(false));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(false));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_NOT_RUNNING, service_error);
 
   // Check that after a failed request, setState RUNNING will go through.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             SetStateAndWaitForResponse(manager_.get(), state));
 }
 
 TEST_F(MediaPerceptionAPIManagerTest, ProcessStateUpstartFailure) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::ProcessState process_state;
   process_state.status = media_perception::PROCESS_STATUS_STARTED;
 
@@ -225,19 +227,19 @@
       process_state,
       base::BindOnce(&RecordServiceErrorFromProcessStateAndRunClosure,
                      run_loop.QuitClosure(), &service_error));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(false));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(false));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_NOT_RUNNING, service_error);
 
   // Check that after a failed request, setState RUNNING will go through.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             SetComponentProcessStateAndWaitForResponse(manager_.get(),
                                                        process_state));
 }
 
 TEST_F(MediaPerceptionAPIManagerTest, UpstartStopFailure) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::State state;
   state.status = media_perception::STATUS_STOPPED;
 
@@ -246,18 +248,18 @@
   manager_->SetState(state,
                      base::Bind(&RecordServiceErrorFromStateAndRunClosure,
                                 run_loop.QuitClosure(), &service_error));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(false));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(false));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_UNREACHABLE, service_error);
 
   // Check that after a failed request, STOPPED will go through.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             SetStateAndWaitForResponse(manager_.get(), state));
 }
 
 TEST_F(MediaPerceptionAPIManagerTest, ProcessStateUpstartStopFailure) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::ProcessState process_state;
   process_state.status = media_perception::PROCESS_STATUS_STOPPED;
 
@@ -267,19 +269,19 @@
       process_state,
       base::BindOnce(&RecordServiceErrorFromProcessStateAndRunClosure,
                      run_loop.QuitClosure(), &service_error));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(false));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(false));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_UNREACHABLE, service_error);
 
   // Check that after a failed request, STOPPED will go through.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             SetComponentProcessStateAndWaitForResponse(manager_.get(),
                                                        process_state));
 }
 
 TEST_F(MediaPerceptionAPIManagerTest, UpstartRestartFailure) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::State state;
   state.status = media_perception::STATUS_RESTARTING;
 
@@ -288,19 +290,19 @@
   manager_->SetState(state,
                      base::Bind(&RecordServiceErrorFromStateAndRunClosure,
                                 run_loop.QuitClosure(), &service_error));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(false));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(false));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_NOT_RUNNING, service_error);
 
   // Check that after a failed request, setState restarted will still go
   // through.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             SetStateAndWaitForResponse(manager_.get(), state));
 }
 
 TEST_F(MediaPerceptionAPIManagerTest, UpstartStall) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::State state;
   state.status = media_perception::STATUS_RUNNING;
 
@@ -314,12 +316,12 @@
             GetStateAndWaitForResponse(manager_.get()));
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_BUSY_LAUNCHING,
             SetStateAndWaitForResponse(manager_.get(), state));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(true));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(true));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE, service_error);
 
   // Verify that after the slow start, things works as normal.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             GetStateAndWaitForResponse(manager_.get()));
   state.status = media_perception::STATUS_SUSPENDED;
@@ -328,7 +330,7 @@
 }
 
 TEST_F(MediaPerceptionAPIManagerTest, SetComponentProcessStateUpstartStall) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::ProcessState process_state;
   process_state.status = media_perception::PROCESS_STATUS_STARTED;
 
@@ -342,19 +344,19 @@
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_BUSY_LAUNCHING,
             SetComponentProcessStateAndWaitForResponse(manager_.get(),
                                                        process_state));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(true));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(true));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE, service_error);
 
   // Verify that after the slow start, things works as normal.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   process_state.status = media_perception::PROCESS_STATUS_STARTED;
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             SetComponentProcessStateAndWaitForResponse(manager_.get(),
                                                        process_state));
 }
 TEST_F(MediaPerceptionAPIManagerTest, UpstartRestartStall) {
-  upstart_client_->set_enqueue_requests(true);
+  upstart_client()->set_enqueue_requests(true);
   media_perception::State state;
   state.status = media_perception::STATUS_RESTARTING;
 
@@ -368,12 +370,12 @@
             GetStateAndWaitForResponse(manager_.get()));
   EXPECT_EQ(media_perception::SERVICE_ERROR_SERVICE_BUSY_LAUNCHING,
             SetStateAndWaitForResponse(manager_.get(), state));
-  EXPECT_TRUE(upstart_client_->HandleNextUpstartRequest(true));
+  EXPECT_TRUE(upstart_client()->HandleNextUpstartRequest(true));
   run_loop.Run();
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE, service_error);
 
   // Verify that after the slow start, things works as normal.
-  upstart_client_->set_enqueue_requests(false);
+  upstart_client()->set_enqueue_requests(false);
   EXPECT_EQ(media_perception::SERVICE_ERROR_NONE,
             GetStateAndWaitForResponse(manager_.get()));
   state.status = media_perception::STATUS_RUNNING;
diff --git a/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc b/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
index bf1779f..cc008bd 100644
--- a/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
+++ b/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
@@ -10,6 +10,7 @@
 #include "chromeos/dbus/fake_media_analytics_client.h"
 #include "chromeos/dbus/media_analytics_client.h"
 #include "chromeos/dbus/media_perception/media_perception.pb.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
 #include "extensions/browser/api/media_perception_private/media_perception_api_delegate.h"
 #include "extensions/browser/api/media_perception_private/media_perception_private_api.h"
 #include "extensions/common/api/media_perception_private.h"
@@ -100,6 +101,9 @@
   void SetUpInProcessBrowserTestFixture() override {
     std::unique_ptr<chromeos::DBusThreadManagerSetter> dbus_setter =
         chromeos::DBusThreadManager::GetSetterForTesting();
+    // Initialize UpstartClient here so that it is available for
+    // FakeMediaAnalyticsClient. It will be shutdown in ChromeBrowserMain.
+    chromeos::UpstartClient::InitializeFake();
     auto media_analytics_client =
         std::make_unique<chromeos::FakeMediaAnalyticsClient>();
     media_analytics_client_ = media_analytics_client.get();
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index 0367a71..fb4b1c3 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -64,6 +64,7 @@
     "039F93DD1DF836F1D4E2084C1BEFDB46A854A9D1",
     "072D729E856B1F2C9894AEEC3A5DF65E519D6BEE",
     "07333481B7B8D7F57A9BA64FB98CF86EA87455FC",
+    "086E69ED9071DCB20C93A081A68360963AB09385",
     "0EAEA2FDEE025D95B3ABB37014EFF5A98AC4BEAE",
     "109A37B889E7C8AEA7B0103559C3EB6AF73B7832",
     "16A81AEA09A67B03F7AEA5B957D24A4095E764BE",
@@ -73,41 +74,61 @@
     "260871EABEDE6F2D07D0D9450096093EDAFCBF34",
     "29427534E31BB1820714C7CAEDF9C54B47BE154F",
     "2AA94E2D3F4DA33F0D3BCF5DD48F69B8BDB26F52",
+    "2E2D8A405430172AB15ADCC09740F3EEE990D605",
+    "31E6100DC7B4EAB4ABF6CA2A4E191D3945D3C731",
+    "3230014EA01150A27C1887B700E019B27A6DBA08",
     "3334952C8387B357A41DD8349D39AD9E7C423943",
+    "34FB670464B5F16EF5ABD6CD53E26030E97C26B3",
     "360D8A88545D0C21CBDE2B55EA9E4E4285282B4C",
+    "3EB17C39F8B6B28FAF34E2406E57A76013A2E066",
     "3FDD3DB17F3B686F5A05204700ABA13DF20AE957",
+    "41536C3554CD9458EB2F05F1B58CF84BB7BF83BC",
     "43865F8D555C201FE452A5A40702EA96240E749C",
+    "44943FADD66932EF56EE3D856A9FAAD4A8AF0FD9",
     "4913450195D177430217CAB64B356DC6F6B0F483",
+    "5053323D1F7B6EEC97A77A350DB6D0D8E51CD0AC",
     "505F2C1E723731B2C8C9182FEAA73D00525B2048",
+    "50DDD8734521B61564FCE273F8E60547F88BBCBE",
+    "52865B2087D0ABCD195A83DFD4BD041A3B4EBC34",
+    "58BCF05A42C8ECED4E6D76F51E2E1A64AC4F7E7C",
+    "5F0C47BC039BEDC1B29B68918F75370C292076A6",
     "61E581B10D83C0AEF8366BB64C18C6615884B3D2",
+    "6357533CAFFB94A9EA5268ED110079E15561E469",
     "67528F9B47BE454EC46809C33D24F2C199BE408D",
     "6AE81EF3B13B15080A2DDB23A205A24C65CCC10B",
     "6BA5F75FFF75B69507BC4B09B7094926EF93DBD2",
     "6E49449D56D031B87835CC767734AF5A064E1A13",
     "71EE66C0F71CD89BEE340F8568A44101D4C3A9A7",
+    "77D83E0A4157A0E77B51AD60BAB69A346CD4FEA3",
     "7BFE588B209A15260DE12777B4BBB738DE98FE6C",
     "808FA9BB3CD501D7801D1CD6D5A3DBA088FDD46F",
     "82FDBBF79F3517C3946BD89EAAF90C46DFDA4681",
     "88C372CE52E21560C17BFD52556E60D694E12CAC",
     "88F5F459139892C0F5DF3022676726BB3F01FB5C",
+    "89F40D84C0C72C6B02B320716E877FB1671218E9",
     "8CDD303D6C341D9CAB16713C3CD7587B90A7A84A",
+    "8CE6227B4E53DF42FF93B24F49D15EDE31E97E79",
     "934B8F5753A3E5A276FC7D0EE5E575B335A0CC76",
     "973E35633030AD27DABEC99609424A61386C7309",
     "99E06C364BBB2D1F82A9D20BC1645BF21E478259",
     "A30E526CF62131BFBFD7CD9B56253A8F3F171777",
     "A3660FA31A0DBF07C9F80D5342FF215DBC962719",
+    "A6057397EDC4E6CF25BC3A142F866ACC653B1CF1",
     "A8FB3967ADE404B77AC3FB5815A399C0660C3C63",
     "A9A4B26C2387BA2A5861C790B0FF39F230427AC8",
     "A9F78610B717B3992F92F490E82FC63FFF46C5FA",
     "AEEDAC793F184240CFB800DA73EE6321E5145102",
+    "B3CF6C01796E8D03378FAA77AF507E27BB847E9D",
     "B4782AE831D849EFCC2AF4BE2012816EDDF8D908",
     "BF5224FB246A6B67EA986EFF77A43F6C1BCA9672",
+    "C5539F4EBECABA792CC40D03A56144AAD3BF9D19",
     "C5BCB9E2E47C3F6FD3F7F83ED982872F77852BA7",
     "CA89BD35059845F2DB4B4398FD339B9F210E9337",
     "CC74B2408753932B5D49C81EC073E3E4CA766EE6",
     "CD8AF9C47DDE6327F8D9A3EFA81F34C6B6C26EBB",
     "CF40F6289951CBFA3B83B792EFA774E2EA06E4C0",
     "D0537B1BADCE856227CE76E31B3772F6B68F653C",
+    "E178D4F4D6617C0B880C36F192DA3B18422C5064",
     "E6B12430B6166B31BE20E13941C22569EA75B0F2",
     "E7036E906DBFB77C46EDDEB003A72C0B5CC9BE7F",
     "E873675B8E754F1B1F1222CB921EA14B4335179D",
@@ -115,10 +136,12 @@
     "EC24668224116D19FF1A5FFAA61238B88773982C",
     "EC4A841BD03C8E5202043165188A9E060BF703A3",
     "EE4BE5F23D2E59E4713958465941EFB4A18166B7",
+    "F273C23C616F5C56E8EDBAE24B21F5D408936A0D",
     "F566B33D62CE21415AF5B3F3FD8762B7454B8874",
     "F59AB261280AB3AE9826D9359507838B90B07431",
     "F73F9EF0207603992CA3C00A7A0CB223D5571B3F",
     "F9287A33E15038F2591F23E6E9C486717C7202DD",
+    "FF0DA4BD87A88469B10709B99E79D4B0E11C0CA6",
 };
 
 constexpr size_t kHashedExtensionIdLength = base::kSHA1Length * 2;
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn
index 157e73a..d29dd5b 100644
--- a/extensions/renderer/BUILD.gn
+++ b/extensions/renderer/BUILD.gn
@@ -158,8 +158,6 @@
     "injection_host.h",
     "ipc_message_sender.cc",
     "ipc_message_sender.h",
-    "js_extension_bindings_system.cc",
-    "js_extension_bindings_system.h",
     "js_renderer_messaging_service.cc",
     "js_renderer_messaging_service.h",
     "lazy_background_page_native_handler.cc",
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 08c7983..fe5b10e1 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -69,7 +69,6 @@
 #include "extensions/renderer/guest_view/guest_view_internal_custom_bindings.h"
 #include "extensions/renderer/id_generator_custom_bindings.h"
 #include "extensions/renderer/ipc_message_sender.h"
-#include "extensions/renderer/js_extension_bindings_system.h"
 #include "extensions/renderer/logging_native_handler.h"
 #include "extensions/renderer/messaging_bindings.h"
 #include "extensions/renderer/messaging_util.h"
diff --git a/extensions/renderer/extension_bindings_system.h b/extensions/renderer/extension_bindings_system.h
index c1cc26b0..413e9f9 100644
--- a/extensions/renderer/extension_bindings_system.h
+++ b/extensions/renderer/extension_bindings_system.h
@@ -28,6 +28,8 @@
 // This is designed to be used on a single thread, but should be safe to use on
 // threads other than the main thread (so that worker threads can have extension
 // bindings).
+// TODO(devlin): There is now only one ExtensionBindingsSystem (the
+// NativeExtensionBindingsSystem); consolidate the classes.
 class ExtensionBindingsSystem {
  public:
   virtual ~ExtensionBindingsSystem() {}
diff --git a/extensions/renderer/js_extension_bindings_system.cc b/extensions/renderer/js_extension_bindings_system.cc
deleted file mode 100644
index 78d870b..0000000
--- a/extensions/renderer/js_extension_bindings_system.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/renderer/js_extension_bindings_system.h"
-
-#include "base/command_line.h"
-#include "base/strings/string_split.h"
-#include "base/timer/elapsed_timer.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/renderer/v8_value_converter.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/extension_api.h"
-#include "extensions/common/extension_urls.h"
-#include "extensions/common/extensions_client.h"
-#include "extensions/common/features/feature.h"
-#include "extensions/common/features/feature_provider.h"
-#include "extensions/common/manifest_constants.h"
-#include "extensions/common/manifest_handlers/externally_connectable.h"
-#include "extensions/renderer/binding_generating_native_handler.h"
-#include "extensions/renderer/event_bindings.h"
-#include "extensions/renderer/event_bookkeeper.h"
-#include "extensions/renderer/ipc_message_sender.h"
-#include "extensions/renderer/renderer_extension_registry.h"
-#include "extensions/renderer/request_sender.h"
-#include "extensions/renderer/resource_bundle_source_map.h"
-#include "extensions/renderer/script_context.h"
-#include "gin/converter.h"
-#include "v8/include/v8.h"
-
-namespace extensions {
-
-namespace {
-
-// Gets |field| from |object| or creates it as an empty object if it doesn't
-// exist.
-v8::Local<v8::Object> GetOrCreateObject(const v8::Local<v8::Object>& object,
-                                        const std::string& field,
-                                        ScriptContext* context) {
-  v8::Local<v8::String> key =
-      v8::String::NewFromUtf8(context->isolate(), field.c_str(),
-                              v8::NewStringType::kInternalized)
-          .ToLocalChecked();
-  // If the object has a callback property, it is assumed it is an unavailable
-  // API, so it is safe to delete. This is checked before GetOrCreateObject is
-  // called.
-  if (object->HasRealNamedCallbackProperty(context->v8_context(), key)
-          .FromMaybe(false)) {
-    object->Delete(context->v8_context(), key).ToChecked();
-  } else if (object->HasRealNamedProperty(context->v8_context(), key)
-                 .FromMaybe(false)) {
-    v8::Local<v8::Value> value =
-        object->Get(context->v8_context(), key).ToLocalChecked();
-    CHECK(value->IsObject());
-    return v8::Local<v8::Object>::Cast(value);
-  }
-
-  v8::Local<v8::Object> new_object = v8::Object::New(context->isolate());
-  object->Set(context->v8_context(), key, new_object).ToChecked();
-  return new_object;
-}
-
-// Returns the global value for "chrome" from |context|. If one doesn't exist
-// creates a new object for it. If a chrome property exists on the window
-// already (as in the case when a script did `window.chrome = true`), returns
-// an empty object.
-v8::Local<v8::Object> GetOrCreateChrome(ScriptContext* context) {
-  v8::Local<v8::String> chrome_string(
-      v8::String::NewFromUtf8(context->isolate(), "chrome",
-                              v8::NewStringType::kInternalized)
-          .ToLocalChecked());
-  v8::Local<v8::Object> global(context->v8_context()->Global());
-  v8::Local<v8::Value> chrome(
-      global->Get(context->v8_context(), chrome_string).ToLocalChecked());
-  if (chrome->IsUndefined()) {
-    chrome = v8::Object::New(context->isolate());
-    global->Set(context->v8_context(), chrome_string, chrome).ToChecked();
-  }
-  return chrome->IsObject() ? chrome.As<v8::Object>() : v8::Local<v8::Object>();
-}
-
-v8::Local<v8::Object> GetOrCreateBindObjectIfAvailable(
-    const std::string& api_name,
-    std::string* bind_name,
-    ScriptContext* context) {
-  std::vector<std::string> split = base::SplitString(
-      api_name, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
-  v8::Local<v8::Object> bind_object;
-
-  // Check if this API has an ancestor. If the API's ancestor is available and
-  // the API is not available, don't install the bindings for this API. If
-  // the API is available and its ancestor is not, delete the ancestor and
-  // install the bindings for the API. This is to prevent loading the ancestor
-  // API schema if it will not be needed.
-  //
-  // For example:
-  //  If app is available and app.window is not, just install app.
-  //  If app.window is available and app is not, delete app and install
-  //  app.window on a new object so app does not have to be loaded.
-  const FeatureProvider* api_feature_provider =
-      FeatureProvider::GetAPIFeatures();
-  std::string ancestor_name;
-  bool only_ancestor_available = false;
-
-  for (size_t i = 0; i < split.size() - 1; ++i) {
-    ancestor_name += (i ? "." : "") + split[i];
-    if (api_feature_provider->GetFeature(ancestor_name) &&
-        context->GetAvailability(ancestor_name).is_available() &&
-        !context->GetAvailability(api_name).is_available()) {
-      only_ancestor_available = true;
-      break;
-    }
-
-    if (bind_object.IsEmpty()) {
-      bind_object = GetOrCreateChrome(context);
-      if (bind_object.IsEmpty())
-        return v8::Local<v8::Object>();
-    }
-    bind_object = GetOrCreateObject(bind_object, split[i], context);
-  }
-
-  if (only_ancestor_available)
-    return v8::Local<v8::Object>();
-
-  DCHECK(bind_name);
-  *bind_name = split.back();
-
-  return bind_object.IsEmpty() ? GetOrCreateChrome(context) : bind_object;
-}
-
-// Creates the event bindings if necessary for the given |context|.
-void MaybeCreateEventBindings(ScriptContext* context) {
-  // chrome.Event is part of the public API (although undocumented). Make it
-  // lazily evalulate to Event from event_bindings.js. For extensions only
-  // though, not all webpages!
-  if (!context->extension())
-    return;
-  v8::Local<v8::Object> chrome = GetOrCreateChrome(context);
-  if (chrome.IsEmpty())
-    return;
-  context->module_system()->SetLazyField(chrome, "Event", kEventBindings,
-                                         "Event");
-}
-
-}  // namespace
-
-JsExtensionBindingsSystem::JsExtensionBindingsSystem(
-    ResourceBundleSourceMap* source_map,
-    std::unique_ptr<IPCMessageSender> ipc_message_sender)
-    : source_map_(source_map),
-      ipc_message_sender_(std::move(ipc_message_sender)),
-      request_sender_(
-          std::make_unique<RequestSender>(ipc_message_sender_.get())),
-      messaging_service_(this) {}
-
-JsExtensionBindingsSystem::~JsExtensionBindingsSystem() {}
-
-void JsExtensionBindingsSystem::DidCreateScriptContext(ScriptContext* context) {
-  MaybeCreateEventBindings(context);
-}
-
-void JsExtensionBindingsSystem::WillReleaseScriptContext(
-    ScriptContext* context) {
-  // TODO(kalman): Make |request_sender| use |context->AddInvalidationObserver|.
-  // In fact |request_sender_| should really be owned by ScriptContext.
-  request_sender_->InvalidateSource(context);
-}
-
-void JsExtensionBindingsSystem::UpdateBindingsForContext(
-    ScriptContext* context) {
-  base::ElapsedTimer timer;
-
-  v8::HandleScope handle_scope(context->isolate());
-  v8::Context::Scope context_scope(context->v8_context());
-
-  // TODO(kalman): Make the bindings registration have zero overhead then run
-  // the same code regardless of context type.
-  switch (context->context_type()) {
-    case Feature::UNSPECIFIED_CONTEXT:
-    case Feature::WEB_PAGE_CONTEXT:
-    case Feature::BLESSED_WEB_PAGE_CONTEXT:
-      // Hard-code registration of any APIs that are exposed to webpage-like
-      // contexts, because it's too expensive to run the full bindings code.
-      // All of the same permission checks will still apply.
-      for (const char* feature_name : kWebAvailableFeatures) {
-        if (context->GetAvailability(feature_name).is_available())
-          RegisterBinding(feature_name, feature_name, context);
-      }
-      if (IsRuntimeAvailableToContext(context))
-        RegisterBinding("runtime", "runtime", context);
-      break;
-
-    case Feature::SERVICE_WORKER_CONTEXT:
-      DCHECK(ExtensionsClient::Get()
-                 ->ExtensionAPIEnabledInExtensionServiceWorkers());
-      FALLTHROUGH;
-    case Feature::BLESSED_EXTENSION_CONTEXT:
-    case Feature::UNBLESSED_EXTENSION_CONTEXT:
-    case Feature::CONTENT_SCRIPT_CONTEXT:
-    case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
-    case Feature::WEBUI_CONTEXT: {
-      // Extension context; iterate through all the APIs and bind the available
-      // ones.
-      const FeatureProvider* api_feature_provider =
-          FeatureProvider::GetAPIFeatures();
-      for (const auto& map_entry : api_feature_provider->GetAllFeatures()) {
-        // Internal APIs are included via require(api_name) from internal code
-        // rather than chrome[api_name].
-        if (map_entry.second->IsInternal())
-          continue;
-
-        // If this API has a parent feature (and isn't marked 'noparent'),
-        // then this must be a function or event, so we should not register.
-        if (api_feature_provider->GetParent(*map_entry.second) != nullptr)
-          continue;
-
-        // Skip chrome.test if this isn't a test.
-        if (map_entry.first == "test" &&
-            !base::CommandLine::ForCurrentProcess()->HasSwitch(
-                ::switches::kTestType)) {
-          continue;
-        }
-
-        if (context->IsAnyFeatureAvailableToContext(
-                *map_entry.second, CheckAliasStatus::NOT_ALLOWED)) {
-          // Check if the API feature is indeed an alias. If it is, the API
-          // should use source API bindings as its own.
-          const std::string& source = map_entry.second->source();
-          // TODO(lazyboy): RegisterBinding() uses |source_map_|, any thread
-          // safety issue?
-          RegisterBinding(source.empty() ? map_entry.first : source,
-                          map_entry.first, context);
-        }
-      }
-      break;
-    }
-  }
-
-  LogUpdateBindingsForContextTime(context->context_type(), timer.Elapsed());
-}
-
-void JsExtensionBindingsSystem::HandleResponse(int request_id,
-                                               bool success,
-                                               const base::ListValue& response,
-                                               const std::string& error) {
-  request_sender_->HandleResponse(request_id, success, response, error);
-  ipc_message_sender_->SendOnRequestResponseReceivedIPC(request_id);
-}
-
-RequestSender* JsExtensionBindingsSystem::GetRequestSender() {
-  return request_sender_.get();
-}
-
-IPCMessageSender* JsExtensionBindingsSystem::GetIPCMessageSender() {
-  return ipc_message_sender_.get();
-}
-
-RendererMessagingService* JsExtensionBindingsSystem::GetMessagingService() {
-  return &messaging_service_;
-}
-
-void JsExtensionBindingsSystem::DispatchEventInContext(
-    const std::string& event_name,
-    const base::ListValue* event_args,
-    const EventFilteringInfo* filtering_info,
-    ScriptContext* context) {
-  EventBindings::DispatchEventInContext(event_name, event_args, filtering_info,
-                                        context);
-}
-
-bool JsExtensionBindingsSystem::HasEventListenerInContext(
-    const std::string& event_name,
-    ScriptContext* context) {
-  return EventBookkeeper::Get()->HasListener(context, event_name);
-}
-
-void JsExtensionBindingsSystem::RegisterBinding(
-    const std::string& api_name,
-    const std::string& api_bind_name,
-    ScriptContext* context) {
-  std::string bind_name;
-  v8::Local<v8::Object> bind_object =
-      GetOrCreateBindObjectIfAvailable(api_bind_name, &bind_name, context);
-
-  // Empty if the bind object failed to be created, probably because the
-  // extension overrode chrome with a non-object, e.g. window.chrome = true.
-  if (bind_object.IsEmpty())
-    return;
-
-  v8::Local<v8::String> v8_bind_name =
-      v8::String::NewFromUtf8(context->isolate(), bind_name.c_str(),
-                              v8::NewStringType::kInternalized)
-          .ToLocalChecked();
-  if (bind_object->HasRealNamedProperty(context->v8_context(), v8_bind_name)
-          .FromMaybe(false)) {
-    // The bind object may already have the property if the API has been
-    // registered before (or if the extension has put something there already,
-    // but, whatevs).
-    //
-    // In the former case, we need to re-register the bindings for the APIs
-    // which the extension now has permissions for (if any), but not touch any
-    // others so that we don't destroy state such as event listeners.
-    //
-    // TODO(kalman): Only register available APIs to make this all moot.
-    if (bind_object
-            ->HasRealNamedCallbackProperty(context->v8_context(), v8_bind_name)
-            .FromMaybe(false))
-      return;  // lazy binding still there, nothing to do
-    if (bind_object->Get(context->v8_context(), v8_bind_name)
-            .ToLocalChecked()
-            ->IsObject())
-      return;  // binding has already been fully installed
-  }
-
-  ModuleSystem* module_system = context->module_system();
-  if (!source_map_->Contains(api_name)) {
-    module_system->RegisterNativeHandler(
-        api_bind_name,
-        std::unique_ptr<NativeHandler>(
-            new BindingGeneratingNativeHandler(context, api_name, "binding")));
-    module_system->SetNativeLazyField(bind_object, bind_name, api_bind_name,
-                                      "binding");
-  } else {
-    module_system->SetLazyField(bind_object, bind_name, api_name, "binding");
-  }
-}
-
-}  // namespace extensions
diff --git a/extensions/renderer/js_extension_bindings_system.h b/extensions/renderer/js_extension_bindings_system.h
deleted file mode 100644
index 78213ac..0000000
--- a/extensions/renderer/js_extension_bindings_system.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef EXTENSIONS_RENDERER_JS_EXTENSION_BINDINGS_SYSTEM_H_
-#define EXTENSIONS_RENDERER_JS_EXTENSION_BINDINGS_SYSTEM_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "extensions/renderer/extension_bindings_system.h"
-#include "extensions/renderer/js_renderer_messaging_service.h"
-
-namespace extensions {
-class IPCMessageSender;
-class ResourceBundleSourceMap;
-
-// The bindings system using the traditional JS-injection style bindings.
-class JsExtensionBindingsSystem : public ExtensionBindingsSystem {
- public:
-  JsExtensionBindingsSystem(ResourceBundleSourceMap* source_map,
-                            std::unique_ptr<IPCMessageSender> request_sender);
-  ~JsExtensionBindingsSystem() override;
-
-  // ExtensionBindingsSystem:
-  void DidCreateScriptContext(ScriptContext* context) override;
-  void WillReleaseScriptContext(ScriptContext* context) override;
-  void UpdateBindingsForContext(ScriptContext* context) override;
-  void DispatchEventInContext(const std::string& event_name,
-                              const base::ListValue* event_args,
-                              const EventFilteringInfo* filtering_info,
-                              ScriptContext* context) override;
-  bool HasEventListenerInContext(const std::string& event_name,
-                                 ScriptContext* context) override;
-  void HandleResponse(int request_id,
-                      bool success,
-                      const base::ListValue& response,
-                      const std::string& error) override;
-  RequestSender* GetRequestSender() override;
-  IPCMessageSender* GetIPCMessageSender() override;
-  RendererMessagingService* GetMessagingService() override;
-
- private:
-  void RegisterBinding(const std::string& api_name,
-                       const std::string& api_bind_name,
-                       ScriptContext* context);
-
-  ResourceBundleSourceMap* source_map_ = nullptr;
-
-  std::unique_ptr<IPCMessageSender> ipc_message_sender_;
-
-  std::unique_ptr<RequestSender> request_sender_;
-
-  JSRendererMessagingService messaging_service_;
-
-  DISALLOW_COPY_AND_ASSIGN(JsExtensionBindingsSystem);
-};
-
-}  // namespace extensions
-
-#endif  // EXTENSIONS_RENDERER_JS_EXTENSION_BINDINGS_SYSTEM_H_
diff --git a/extensions/renderer/worker_thread_dispatcher.cc b/extensions/renderer/worker_thread_dispatcher.cc
index 5a48537..a6d6ba3a 100644
--- a/extensions/renderer/worker_thread_dispatcher.cc
+++ b/extensions/renderer/worker_thread_dispatcher.cc
@@ -20,8 +20,7 @@
 #include "extensions/renderer/dispatcher.h"
 #include "extensions/renderer/extension_bindings_system.h"
 #include "extensions/renderer/extensions_renderer_client.h"
-#include "extensions/renderer/js_extension_bindings_system.h"
-#include "extensions/renderer/native_extension_bindings_system.h"
+#include "extensions/renderer/renderer_messaging_service.h"
 #include "extensions/renderer/service_worker_data.h"
 #include "extensions/renderer/worker_script_context_set.h"
 
diff --git a/fuchsia/engine/browser/context_impl_browsertest.cc b/fuchsia/engine/browser/context_impl_browsertest.cc
index c2b5267..8a51d49 100644
--- a/fuchsia/engine/browser/context_impl_browsertest.cc
+++ b/fuchsia/engine/browser/context_impl_browsertest.cc
@@ -95,7 +95,7 @@
     EXPECT_CALL(navigation_observer_, MockableOnNavigationStateChanged(_))
         .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
 
-    nav->LoadUrl(cookie_url.spec(), nullptr);
+    nav->LoadUrl(cookie_url.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 
@@ -153,7 +153,7 @@
               MockableOnNavigationStateChanged(
                   Field(&NavigationDetails::url, url::kAboutBlankURL)))
       .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-  controller->LoadUrl(url::kAboutBlankURL, nullptr);
+  controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams());
   run_loop.Run();
 
   frame.Unbind();
@@ -171,7 +171,7 @@
   EXPECT_CALL(navigation_observer_, MockableOnNavigationStateChanged(_))
       .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
 
-  nav->LoadUrl(cookie_url.spec(), nullptr);
+  nav->LoadUrl(cookie_url.spec(), chromium::web::LoadUrlParams());
   run_loop.Run();
 
   auto cookies = GetCookies();
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
index e1e2e6b..648b7b9 100644
--- a/fuchsia/engine/browser/frame_impl.cc
+++ b/fuchsia/engine/browser/frame_impl.cc
@@ -447,20 +447,7 @@
       });
 }
 
-void FrameImpl::LoadUrl(std::string url,
-                        std::unique_ptr<chromium::web::LoadUrlParams> params) {
-  chromium::web::LoadUrlParams2 converted_params;
-  if (params) {
-    converted_params.set_type(params->type);
-    converted_params.set_referrer_url(std::move(params->referrer));
-    converted_params.set_was_user_activated(params->user_activated);
-    converted_params.set_headers(std::move(params->headers));
-  }
-  LoadUrl2(std::move(url), std::move(converted_params));
-}
-
-void FrameImpl::LoadUrl2(std::string url,
-                         chromium::web::LoadUrlParams2 params) {
+void FrameImpl::LoadUrl(std::string url, chromium::web::LoadUrlParams params) {
   GURL validated_url(url);
   if (!validated_url.is_valid()) {
     // TODO(crbug.com/934539): Add type epitaph.
@@ -492,6 +479,24 @@
   web_contents_->GetController().LoadURLWithParams(params_converted);
 }
 
+void FrameImpl::LoadUrl2(std::string url,
+                         chromium::web::LoadUrlParams2 params) {
+  chromium::web::LoadUrlParams converted_params;
+  if (params.has_type()) {
+    converted_params.set_type(*params.type());
+  }
+  if (params.has_referrer_url()) {
+    converted_params.set_referrer_url(std::move(*params.referrer_url()));
+  }
+  if (params.has_was_user_activated()) {
+    converted_params.set_was_user_activated(*params.was_user_activated());
+  }
+  if (params.has_headers()) {
+    converted_params.set_headers(std::move(*params.headers()));
+  }
+  LoadUrl(std::move(url), std::move(converted_params));
+}
+
 void FrameImpl::GoBack() {
   if (web_contents_->GetController().CanGoBack())
     web_contents_->GetController().GoBack();
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
index 2fad2f89..361109e 100644
--- a/fuchsia/engine/browser/frame_impl.h
+++ b/fuchsia/engine/browser/frame_impl.h
@@ -105,8 +105,7 @@
   void MaybeSendNavigationEvent();
 
   // chromium::web::NavigationController implementation.
-  void LoadUrl(std::string url,
-               std::unique_ptr<chromium::web::LoadUrlParams> params) override;
+  void LoadUrl(std::string url, chromium::web::LoadUrlParams params) override;
   void LoadUrl2(std::string url, chromium::web::LoadUrlParams2 params) override;
   void GoBack() override;
   void GoForward() override;
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc
index 21bc1f2d..9d5d28d2 100644
--- a/fuchsia/engine/browser/frame_impl_browsertest.cc
+++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -73,7 +73,7 @@
   // Navigates a |controller| to |url|, blocking until navigation is complete.
   void CheckLoadUrl(const std::string& url,
                     const std::string& expected_title,
-                    chromium::web::LoadUrlParams2 load_url_params,
+                    chromium::web::LoadUrlParams load_url_params,
                     chromium::web::NavigationController* controller) {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
@@ -81,7 +81,7 @@
                     Field(&NavigationDetails::title, expected_title),
                     Field(&NavigationDetails::url, url))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl2(url, std::move(load_url_params));
+    controller->LoadUrl(url, std::move(load_url_params));
     run_loop.Run();
     Mock::VerifyAndClearExpectations(this);
     navigation_observer_.Acknowledge();
@@ -113,7 +113,7 @@
   frame->GetNavigationController(controller.NewRequest());
 
   CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL,
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 }
 
 // TODO(crbug.com/931831): Remove this test once the transition is complete.
@@ -129,7 +129,7 @@
                   Field(&NavigationDetails::title, url::kAboutBlankURL),
                   Field(&NavigationDetails::url, url::kAboutBlankURL))))
       .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-  controller->LoadUrl(url::kAboutBlankURL, nullptr);
+  controller->LoadUrl2(url::kAboutBlankURL, chromium::web::LoadUrlParams2());
   run_loop.Run();
   Mock::VerifyAndClearExpectations(this);
   navigation_observer_.Acknowledge();
@@ -141,7 +141,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
 
-  CheckLoadUrl(kDataUrl, kDataUrl, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(kDataUrl, kDataUrl, chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -160,7 +160,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  controller->LoadUrl2(url::kAboutBlankURL, chromium::web::LoadUrlParams2());
+  controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams());
 
   frame.Unbind();
   run_loop.Run();
@@ -214,9 +214,9 @@
   GURL title1(embedded_test_server()->GetURL(kPage1Path));
   GURL title2(embedded_test_server()->GetURL(kPage2Path));
 
-  CheckLoadUrl(title1.spec(), kPage1Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(title1.spec(), kPage1Title, chromium::web::LoadUrlParams(),
                controller.get());
-  CheckLoadUrl(title2.spec(), kPage2Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(title2.spec(), kPage2Title, chromium::web::LoadUrlParams(),
                controller.get());
 
   {
@@ -268,7 +268,7 @@
   GURL url(embedded_test_server()->GetURL(kPage1Path));
 
   EXPECT_CALL(*this, OnServeHttpRequest(_));
-  CheckLoadUrl(url.spec(), kPage1Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), kPage1Title, chromium::web::LoadUrlParams(),
                navigation_controller.get());
 
   navigation_observer_.Observe(
@@ -326,7 +326,7 @@
                     Field(&NavigationDetails::title, kPage1Title),
                     Field(&NavigationDetails::url, IsSet()))))
         .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
-    controller->LoadUrl(title1.spec(), nullptr);
+    controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
     navigation_observer_.Acknowledge();
   }
@@ -353,7 +353,7 @@
                     Field(&NavigationDetails::title, kPage2Title),
                     Field(&NavigationDetails::url, IsSet()))))
         .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
-    controller->LoadUrl(title2.spec(), nullptr);
+    controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
     navigation_observer_.Acknowledge();
   }
@@ -419,7 +419,7 @@
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title1))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title1.spec(), nullptr);
+    controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 
@@ -427,7 +427,7 @@
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title2))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title2.spec(), nullptr);
+    controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 }
@@ -442,7 +442,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(title1.spec(), kPage1Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(title1.spec(), kPage1Title, chromium::web::LoadUrlParams(),
                controller.get());
   std::vector<std::string> origins = {title1.GetOrigin().spec()};
 
@@ -477,7 +477,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -496,7 +496,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -519,7 +519,7 @@
   // Expect that the original HTML title is used, because we didn't inject a
   // script with a replacement title.
   CheckLoadUrl(url.spec(), "Welcome to Stan the Offline Dino's Homepage",
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 }
 
 IN_PROC_BROWSER_TEST_F(FrameImplTest, ExecuteJavaScriptOnLoadWildcardOrigin) {
@@ -538,16 +538,16 @@
   // Test script injection for the origin 127.0.0.1.
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams(),
                controller.get());
 
   CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL,
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   // Test script injection using a different origin ("localhost"), which should
   // still be picked up by the wildcard.
   GURL alt_url = embedded_test_server()->GetURL("localhost", kDynamicTitlePath);
-  CheckLoadUrl(alt_url.spec(), "hello", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(alt_url.spec(), "hello", chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -571,7 +571,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(url.spec(), "hello there", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), "hello there", chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -590,7 +590,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), "hello", chromium::web::LoadUrlParams(),
                controller.get());
 
   frame->ExecuteJavaScript(
@@ -601,10 +601,10 @@
 
   // Navigate away to clean the slate.
   CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL,
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   // Navigate back and see if both scripts are working.
-  CheckLoadUrl(url.spec(), "hello there", chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), "hello there", chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -616,7 +616,7 @@
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
-  CheckLoadUrl(url.spec(), kPage1Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(url.spec(), kPage1Title, chromium::web::LoadUrlParams(),
                controller.get());
 
   base::RunLoop run_loop;
@@ -655,7 +655,7 @@
                     Field(&NavigationDetails::title, kPage1Title),
                     Field(&NavigationDetails::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title1.spec(), nullptr);
+    controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 
@@ -668,7 +668,7 @@
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title2))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title2.spec(), nullptr);
+    controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 }
@@ -692,7 +692,7 @@
                     Field(&NavigationDetails::title, kPage1Title),
                     Field(&NavigationDetails::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title1.spec(), nullptr);
+    controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
     Mock::VerifyAndClearExpectations(this);
   }
@@ -707,7 +707,7 @@
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title2))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title2.spec(), nullptr);
+    controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
     Mock::VerifyAndClearExpectations(this);
   }
@@ -717,7 +717,7 @@
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title1))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(title1.spec(), nullptr);
+    controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
     Mock::VerifyAndClearExpectations(this);
   }
@@ -763,7 +763,7 @@
     base::RunLoop run_loop;
     EXPECT_CALL(observer, DidStartNavigation(_))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    controller->LoadUrl(hung_url.spec(), nullptr);
+    controller->LoadUrl(hung_url.spec(), chromium::web::LoadUrlParams());
     run_loop.Run();
     Mock::VerifyAndClearExpectations(this);
   }
@@ -794,7 +794,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
   CheckLoadUrl(post_message_url.spec(), "postmessage",
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   chromium::web::WebMessage message;
   message.data = cr_fuchsia::MemBufferFromString(kPage1Path);
@@ -823,7 +823,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
   CheckLoadUrl(post_message_url.spec(), "messageport",
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   chromium::web::MessagePortPtr message_port;
   chromium::web::WebMessage msg;
@@ -874,7 +874,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
   CheckLoadUrl(post_message_url.spec(), "messageport",
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   chromium::web::MessagePortPtr message_port;
   chromium::web::WebMessage msg;
@@ -904,7 +904,7 @@
     base::RunLoop run_loop;
     message_port.set_error_handler(
         [&run_loop](zx_status_t) { run_loop.Quit(); });
-    controller->LoadUrl(url::kAboutBlankURL, nullptr);
+    controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 }
@@ -921,7 +921,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
   CheckLoadUrl(post_message_url.spec(), "messageport",
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   chromium::web::MessagePortPtr incoming_message_port;
   chromium::web::WebMessage msg;
@@ -1007,7 +1007,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
   CheckLoadUrl(post_message_url.spec(), "messageport",
-               chromium::web::LoadUrlParams2(), controller.get());
+               chromium::web::LoadUrlParams(), controller.get());
 
   chromium::web::MessagePortPtr bad_origin_incoming_message_port;
   chromium::web::WebMessage msg;
@@ -1073,7 +1073,7 @@
 
   // Verify that the Frame can navigate, prior to the View being created.
   const GURL page1_url(embedded_test_server()->GetURL(kPage1Path));
-  CheckLoadUrl(page1_url.spec(), kPage1Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(page1_url.spec(), kPage1Title, chromium::web::LoadUrlParams(),
                controller.get());
 
   // Request a View from the Frame, and pump the loop to process the request.
@@ -1085,7 +1085,7 @@
 
   // Verify that the Frame still works, by navigating to Page #2.
   const GURL page2_url(embedded_test_server()->GetURL(kPage2Path));
-  CheckLoadUrl(page2_url.spec(), kPage2Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(page2_url.spec(), kPage2Title, chromium::web::LoadUrlParams(),
                controller.get());
 
   // Create new View tokens and request a new view.
@@ -1096,7 +1096,7 @@
   EXPECT_TRUE(frame_impl->has_view_for_test());
 
   // Verify that the Frame still works, by navigating back to Page #1.
-  CheckLoadUrl(page1_url.spec(), kPage1Title, chromium::web::LoadUrlParams2(),
+  CheckLoadUrl(page1_url.spec(), kPage1Title, chromium::web::LoadUrlParams(),
                controller.get());
 }
 
@@ -1148,7 +1148,7 @@
 IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest, ExtraHeaders) {
   chromium::web::FramePtr frame = CreateFrame();
 
-  chromium::web::LoadUrlParams2 load_url_params;
+  chromium::web::LoadUrlParams load_url_params;
   load_url_params.set_headers({StringToUnsignedVector("X-ExtraHeaders: 1"),
                                StringToUnsignedVector("X-2ExtraHeaders: 2")});
 
@@ -1175,12 +1175,9 @@
                        DeprecatedExtraHeaders) {
   chromium::web::FramePtr frame = CreateFrame();
 
-  chromium::web::LoadUrlParamsPtr load_url_params =
-      chromium::web::LoadUrlParams::New();
-  load_url_params->headers.push_back(
-      StringToUnsignedVector("X-ExtraHeaders: 1"));
-  load_url_params->headers.push_back(
-      StringToUnsignedVector("X-2ExtraHeaders: 2"));
+  chromium::web::LoadUrlParams2 load_url_params;
+  load_url_params.set_headers({StringToUnsignedVector("X-ExtraHeaders: 1"),
+                               StringToUnsignedVector("X-2ExtraHeaders: 2")});
 
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
@@ -1193,7 +1190,7 @@
                   Field(&NavigationDetails::title, kPage1Title),
                   Field(&NavigationDetails::url, page_url.spec()))))
       .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-  controller->LoadUrl(page_url.spec(), std::move(load_url_params));
+  controller->LoadUrl2(page_url.spec(), std::move(load_url_params));
   run_loop.Run();
   Mock::VerifyAndClearExpectations(this);
   navigation_observer_.Acknowledge();
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index fc471f0d..deb06da 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -54,23 +54,6 @@
 
 void ContextProviderImpl::Create(
     chromium::web::CreateContextParams params,
-    ::fidl::InterfaceRequest<chromium::web::Context> context_request) {
-  chromium::web::CreateContextParams2 converted_params;
-
-  converted_params.set_service_directory(
-      fidl::InterfaceHandle<fuchsia::io::Directory>(
-          std::move(params.service_directory)));
-
-  if (params.data_directory) {
-    converted_params.set_data_directory(
-        fidl::InterfaceHandle<fuchsia::io::Directory>(
-            std::move(params.data_directory)));
-  }
-  Create2(std::move(converted_params), std::move(context_request));
-}
-
-void ContextProviderImpl::Create2(
-    chromium::web::CreateContextParams2 params,
     fidl::InterfaceRequest<chromium::web::Context> context_request) {
   if (!context_request.is_valid()) {
     // TODO(crbug.com/934539): Add type epitaph.
@@ -80,7 +63,7 @@
   if (!params.has_service_directory()) {
     // TODO(crbug.com/934539): Add type epitaph.
     DLOG(WARNING)
-        << "Missing argument |service_directory| in CreateContextParams2.";
+        << "Missing argument |service_directory| in CreateContextParams.";
     return;
   }
 
@@ -104,7 +87,7 @@
     if (data_directory_channel.get() == ZX_HANDLE_INVALID) {
       // TODO(crbug.com/934539): Add type epitaph.
       DLOG(WARNING)
-          << "Invalid argument |data_directory| in CreateContextParams2.";
+          << "Invalid argument |data_directory| in CreateContextParams.";
       return;
     }
 
@@ -139,6 +122,21 @@
   ignore_result(context_handle.release());
 }
 
+void ContextProviderImpl::Create2(
+    chromium::web::CreateContextParams2 params,
+    ::fidl::InterfaceRequest<chromium::web::Context> context_request) {
+  chromium::web::CreateContextParams converted_params;
+  if (params.has_service_directory()) {
+    converted_params.set_service_directory(
+        std::move(*params.mutable_service_directory()));
+  }
+  if (params.has_data_directory()) {
+    converted_params.set_data_directory(
+        std::move(*params.mutable_data_directory()));
+  }
+  Create(std::move(converted_params), std::move(context_request));
+}
+
 void ContextProviderImpl::Bind(
     fidl::InterfaceRequest<chromium::web::ContextProvider> request) {
   bindings_.AddBinding(this, std::move(request));
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc
index ab1820e..9b3d3a4 100644
--- a/fuchsia/engine/context_provider_impl_unittest.cc
+++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -145,7 +145,20 @@
     EXPECT_EQ(change_observer.captured_event().title, kTitle);
   }
 
-  chromium::web::CreateContextParams2 BuildCreateContextParams() {
+  chromium::web::CreateContextParams BuildCreateContextParams() {
+    fidl::InterfaceHandle<fuchsia::io::Directory> directory;
+    zx_status_t result =
+        fdio_service_connect(base::fuchsia::kServiceDirectoryPath,
+                             directory.NewRequest().TakeChannel().release());
+    ZX_CHECK(result == ZX_OK, result) << "Failed to open /svc";
+
+    chromium::web::CreateContextParams output;
+    output.set_service_directory(std::move(directory));
+    return output;
+  }
+
+  // TODO(crbug.com/931831): Remove this method once the transition is complete.
+  chromium::web::CreateContextParams2 BuildDeprecatedCreateContextParams() {
     fidl::InterfaceHandle<fuchsia::io::Directory> directory;
     zx_status_t result =
         fdio_service_connect(base::fuchsia::kServiceDirectoryPath,
@@ -157,22 +170,6 @@
     return output;
   }
 
-  // TODO(crbug.com/931831): Remove this method once the transition is complete.
-  chromium::web::CreateContextParams BuildDeprecatedCreateContextParams() {
-    zx::channel client_channel;
-    zx::channel server_channel;
-    zx_status_t result =
-        zx::channel::create(0, &client_channel, &server_channel);
-    ZX_CHECK(result == ZX_OK, result) << "zx_channel_create()";
-    result = fdio_service_connect(base::fuchsia::kServiceDirectoryPath,
-                                  server_channel.release());
-    ZX_CHECK(result == ZX_OK, result) << "Failed to open /svc";
-
-    chromium::web::CreateContextParams output;
-    output.service_directory = std::move(client_channel);
-    return output;
-  }
-
   // Checks that the Context channel was dropped.
   void CheckContextUnresponsive(
       fidl::InterfacePtr<chromium::web::Context>* context) {
@@ -222,9 +219,8 @@
 TEST_F(ContextProviderImplTest, LaunchContext) {
   // Connect to a new context process.
   fidl::InterfacePtr<chromium::web::Context> context;
-  chromium::web::CreateContextParams2 create_params =
-      BuildCreateContextParams();
-  provider_ptr_->Create2(std::move(create_params), context.NewRequest());
+  chromium::web::CreateContextParams create_params = BuildCreateContextParams();
+  provider_ptr_->Create(std::move(create_params), context.NewRequest());
   CheckContextResponsive(&context);
 }
 
@@ -232,9 +228,9 @@
 TEST_F(ContextProviderImplTest, DeprecatedLaunchContext) {
   // Connect to a new context process.
   fidl::InterfacePtr<chromium::web::Context> context;
-  chromium::web::CreateContextParams create_params =
+  chromium::web::CreateContextParams2 create_params =
       BuildDeprecatedCreateContextParams();
-  provider_ptr_->Create(std::move(create_params), context.NewRequest());
+  provider_ptr_->Create2(std::move(create_params), context.NewRequest());
   CheckContextResponsive(&context);
 }
 
@@ -243,13 +239,13 @@
   chromium::web::ContextProviderPtr provider_1_ptr;
   provider_->Bind(provider_1_ptr.NewRequest());
   chromium::web::ContextPtr context_1;
-  provider_1_ptr->Create2(BuildCreateContextParams(), context_1.NewRequest());
+  provider_1_ptr->Create(BuildCreateContextParams(), context_1.NewRequest());
 
   // Do the same on another Provider connection.
   chromium::web::ContextProviderPtr provider_2_ptr;
   provider_->Bind(provider_2_ptr.NewRequest());
   chromium::web::ContextPtr context_2;
-  provider_2_ptr->Create2(BuildCreateContextParams(), context_2.NewRequest());
+  provider_2_ptr->Create(BuildCreateContextParams(), context_2.NewRequest());
 
   CheckContextResponsive(&context_1);
   CheckContextResponsive(&context_2);
@@ -257,7 +253,7 @@
   // Ensure that the initial ContextProvider connection is still usable, by
   // creating and verifying another Context from it.
   chromium::web::ContextPtr context_3;
-  provider_2_ptr->Create2(BuildCreateContextParams(), context_3.NewRequest());
+  provider_2_ptr->Create(BuildCreateContextParams(), context_3.NewRequest());
   CheckContextResponsive(&context_3);
 }
 
@@ -266,8 +262,39 @@
 
   // Connect to a new context process.
   fidl::InterfacePtr<chromium::web::Context> context;
+  chromium::web::CreateContextParams create_params = BuildCreateContextParams();
+
+  // Setup data dir.
+  EXPECT_TRUE(profile_temp_dir.CreateUniqueTempDir());
+  ASSERT_EQ(
+      base::WriteFile(profile_temp_dir.GetPath().AppendASCII(kTestDataFileIn),
+                      nullptr, 0),
+      0);
+
+  // Pass a handle data dir to the context.
+  create_params.set_data_directory(
+      fidl::InterfaceHandle<fuchsia::io::Directory>(
+          zx::channel(base::fuchsia::GetHandleFromFile(
+              base::File(profile_temp_dir.GetPath(),
+                         base::File::FLAG_OPEN | base::File::FLAG_READ)))));
+
+  provider_ptr_->Create(std::move(create_params), context.NewRequest());
+
+  CheckContextResponsive(&context);
+
+  // Verify that the context process can write to the data dir.
+  EXPECT_TRUE(base::PathExists(
+      profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut)));
+}
+
+// TODO(crbug.com/931831): Remove this test once the transition is complete.
+TEST_F(ContextProviderImplTest, DeprecatedWithProfileDir) {
+  base::ScopedTempDir profile_temp_dir;
+
+  // Connect to a new context process.
+  fidl::InterfacePtr<chromium::web::Context> context;
   chromium::web::CreateContextParams2 create_params =
-      BuildCreateContextParams();
+      BuildDeprecatedCreateContextParams();
 
   // Setup data dir.
   EXPECT_TRUE(profile_temp_dir.CreateUniqueTempDir());
@@ -292,45 +319,12 @@
       profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut)));
 }
 
-// TODO(crbug.com/931831): Remove this test once the transition is complete.
-TEST_F(ContextProviderImplTest, DeprecatedWithProfileDir) {
-  base::ScopedTempDir profile_temp_dir;
-
-  // Connect to a new context process.
-  fidl::InterfacePtr<chromium::web::Context> context;
-  chromium::web::CreateContextParams create_params =
-      BuildDeprecatedCreateContextParams();
-
-  // Setup data dir.
-  EXPECT_TRUE(profile_temp_dir.CreateUniqueTempDir());
-  ASSERT_EQ(
-      base::WriteFile(profile_temp_dir.GetPath().AppendASCII(kTestDataFileIn),
-                      nullptr, 0),
-      0);
-
-  // Pass a handle data dir to the context.
-  create_params.data_directory.reset(
-      base::fuchsia::GetHandleFromFile(
-          base::File(profile_temp_dir.GetPath(),
-                     base::File::FLAG_OPEN | base::File::FLAG_READ))
-          .release());
-
-  provider_ptr_->Create(std::move(create_params), context.NewRequest());
-
-  CheckContextResponsive(&context);
-
-  // Verify that the context process can write to the data dir.
-  EXPECT_TRUE(base::PathExists(
-      profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut)));
-}
-
 TEST_F(ContextProviderImplTest, FailsDataDirectoryIsFile) {
   base::FilePath temp_file_path;
 
   // Connect to a new context process.
   fidl::InterfacePtr<chromium::web::Context> context;
-  chromium::web::CreateContextParams2 create_params =
-      BuildCreateContextParams();
+  chromium::web::CreateContextParams create_params = BuildCreateContextParams();
 
   // Pass in a handle to a file instead of a directory.
   CHECK(base::CreateTemporaryFile(&temp_file_path));
@@ -340,7 +334,7 @@
               base::File(temp_file_path,
                          base::File::FLAG_OPEN | base::File::FLAG_READ)))));
 
-  provider_ptr_->Create2(std::move(create_params), context.NewRequest());
+  provider_ptr_->Create(std::move(create_params), context.NewRequest());
 
   CheckContextUnresponsive(&context);
 }
@@ -370,7 +364,7 @@
 
   // Create a Context and verify that it is functional.
   chromium::web::ContextPtr context;
-  provider->Create2(BuildCreateContextParams(), context.NewRequest());
+  provider->Create(BuildCreateContextParams(), context.NewRequest());
   CheckContextResponsive(&context);
 
   // Verify that there is at least one job under our default job.
diff --git a/fuchsia/fidl/web/context_provider.fidl b/fuchsia/fidl/web/context_provider.fidl
index af22a09..1092d64 100644
--- a/fuchsia/fidl/web/context_provider.fidl
+++ b/fuchsia/fidl/web/context_provider.fidl
@@ -15,25 +15,25 @@
   ///
   /// context: An interface request which will receive a bound Context
   ///          service.
-  // DEPRECATED Use Create2 instead.
   Create(CreateContextParams params, request<Context> context);
 
+  // DEPRECATED Use Create instead.
   Create2(CreateContextParams2 params, request<Context> context);
 };
 
-// DEPRECATED Use CreateContextParams2 instead.
-struct CreateContextParams {
+table CreateContextParams {
   /// Service directory to be used by the context.
   // TODO(https://crbug.com/870057): Document required and optional services
   // that Context needs.
-  handle<channel> service_directory;
+  1: fuchsia.io.Directory service_directory;
 
   /// Handle to the directory that will contain the Context's
   /// persistent data. If it is left unset, then the created Context will be
   /// stateless, with all of its data discarded upon Context destruction.
-  handle<channel>? data_directory;
+  2: fuchsia.io.Directory data_directory;
 };
 
+// DEPRECATED Use CreateContextParams instead.
 table CreateContextParams2 {
   /// Service directory to be used by the context.
   // TODO(https://crbug.com/870057): Document required and optional services
diff --git a/fuchsia/fidl/web/navigation_controller.fidl b/fuchsia/fidl/web/navigation_controller.fidl
index 674afb5..eb3e149 100644
--- a/fuchsia/fidl/web/navigation_controller.fidl
+++ b/fuchsia/fidl/web/navigation_controller.fidl
@@ -12,9 +12,9 @@
   /// |url|:    The address to navigate to.
   /// |params|: Additional parameters that affect how the resource will be
   ///           loaded (e.g. cookies, HTTP headers, etc.)
-  // DEPRECATED Use LoadUrl2 instead.
-  LoadUrl(string url, LoadUrlParams? params);
+  LoadUrl(string url, LoadUrlParams params);
 
+  // DEPRECATED Use LoadUrl instead.
   LoadUrl2(string url, LoadUrlParams2 params);
 
   GoBack();
@@ -28,25 +28,25 @@
 };
 
 /// Additional parameters for modifying the behavior of LoadUrl().
-// DEPRECATED Use LoadUrlParams2 instead.
-struct LoadUrlParams {
+table LoadUrlParams {
   /// Provides a hint to the browser UI about how LoadUrl was triggered.
-  LoadUrlReason type;
+  1: LoadUrlReason type;
 
   /// The URL that linked to the resource being requested.
-  string referrer;
+  2: string referrer_url;
 
   /// Should be set to true to propagate user activation to the frame. User
   /// activation implies that the user is interacting with the web frame. It
   /// enables some web features that are not available otherwise. For example
   /// autoplay will work only when this flag is set to true.
-  bool user_activated = false;
+  3: bool was_user_activated;
 
   /// Custom HTTP headers.
-  vector<bytes> headers;
+  4: vector<bytes> headers;
 };
 
 /// Additional parameters for modifying the behavior of LoadUrl().
+// DEPRECATED Use LoadUrlParams instead.
 table LoadUrlParams2 {
   /// Provides a hint to the browser UI about how LoadUrl was triggered.
   1: LoadUrlReason type;
diff --git a/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc b/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc
index 59ebab8..a2869d0 100644
--- a/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc
+++ b/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc
@@ -102,7 +102,7 @@
   void CheckLoadUrl(const std::string& url,
                     chromium::web::NavigationController* controller) {
     navigate_run_loop_ = std::make_unique<base::RunLoop>();
-    controller->LoadUrl(url, nullptr);
+    controller->LoadUrl(url, chromium::web::LoadUrlParams());
     navigate_run_loop_->Run();
     navigate_run_loop_.reset();
   }
diff --git a/fuchsia/runners/cast/named_message_port_connector_browsertest.cc b/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
index 90c918d6..4263679d 100644
--- a/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
+++ b/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
@@ -56,7 +56,7 @@
   void CheckLoadUrl(const std::string& url,
                     chromium::web::NavigationController* controller) {
     navigate_run_loop_ = std::make_unique<base::RunLoop>();
-    controller->LoadUrl(url, nullptr);
+    controller->LoadUrl(url, chromium::web::LoadUrlParams());
     navigate_run_loop_->Run();
     navigate_run_loop_.reset();
   }
@@ -118,7 +118,7 @@
     (*message_port).set_error_handler([&run_loop](zx_status_t) {
       run_loop.Quit();
     });
-    controller->LoadUrl("about:blank", nullptr);
+    controller->LoadUrl("about:blank", chromium::web::LoadUrlParams());
     run_loop.Run();
   }
 
diff --git a/fuchsia/runners/cast/queryable_data_bindings_browsertest.cc b/fuchsia/runners/cast/queryable_data_bindings_browsertest.cc
index 821dbad3..1d6ee45b 100644
--- a/fuchsia/runners/cast/queryable_data_bindings_browsertest.cc
+++ b/fuchsia/runners/cast/queryable_data_bindings_browsertest.cc
@@ -34,7 +34,7 @@
   void CheckLoadUrl(const std::string& url,
                     chromium::web::NavigationController* controller) {
     navigate_run_loop_ = std::make_unique<base::RunLoop>();
-    controller->LoadUrl(url, nullptr);
+    controller->LoadUrl(url, chromium::web::LoadUrlParams());
     navigate_run_loop_->Run();
     navigate_run_loop_.reset();
   }
diff --git a/fuchsia/runners/common/web_component.cc b/fuchsia/runners/common/web_component.cc
index 8981749..2445e96 100644
--- a/fuchsia/runners/common/web_component.cc
+++ b/fuchsia/runners/common/web_component.cc
@@ -27,10 +27,10 @@
   // Set the page activation flag on the initial load, so that features like
   // autoplay work as expected when a WebComponent first loads the specified
   // content.
-  chromium::web::LoadUrlParams2 params;
+  chromium::web::LoadUrlParams params;
   params.set_was_user_activated(true);
 
-  navigation_controller->LoadUrl2(url.spec(), std::move(params));
+  navigation_controller->LoadUrl(url.spec(), std::move(params));
 }
 
 WebComponent::WebComponent(
diff --git a/ios/chrome/browser/autofill/autofill_tab_helper.h b/ios/chrome/browser/autofill/autofill_tab_helper.h
index 7d0f53e..70499011 100644
--- a/ios/chrome/browser/autofill/autofill_tab_helper.h
+++ b/ios/chrome/browser/autofill/autofill_tab_helper.h
@@ -20,7 +20,7 @@
 }
 
 namespace password_manager {
-class PasswordGenerationManager;
+class PasswordManager;
 }
 
 namespace ios {
@@ -36,7 +36,7 @@
   // Create an AutofillTabHelper and attaches it to the given |web_state|.
   static void CreateForWebState(
       web::WebState* web_state,
-      password_manager::PasswordGenerationManager* password_generation_manager);
+      password_manager::PasswordManager* password_manager);
 
   // Sets a weak reference to the view controller used to present UI.
   void SetBaseViewController(UIViewController* base_view_controller);
@@ -47,9 +47,8 @@
  private:
   friend class web::WebStateUserData<AutofillTabHelper>;
 
-  AutofillTabHelper(
-      web::WebState* web_state,
-      password_manager::PasswordGenerationManager* password_generation_manager);
+  AutofillTabHelper(web::WebState* web_state,
+                    password_manager::PasswordManager* password_manager);
 
   // web::WebStateObserver implementation.
   void WebStateDestroyed(web::WebState* web_state) override;
diff --git a/ios/chrome/browser/autofill/autofill_tab_helper.mm b/ios/chrome/browser/autofill/autofill_tab_helper.mm
index 9c5e96a..9fa3d86 100644
--- a/ios/chrome/browser/autofill/autofill_tab_helper.mm
+++ b/ios/chrome/browser/autofill/autofill_tab_helper.mm
@@ -22,12 +22,12 @@
 // static
 void AutofillTabHelper::CreateForWebState(
     web::WebState* web_state,
-    password_manager::PasswordGenerationManager* password_generation_manager) {
+    password_manager::PasswordManager* password_manager) {
   DCHECK(web_state);
   if (!FromWebState(web_state)) {
-    web_state->SetUserData(UserDataKey(),
-                           base::WrapUnique(new AutofillTabHelper(
-                               web_state, password_generation_manager)));
+    web_state->SetUserData(
+        UserDataKey(),
+        base::WrapUnique(new AutofillTabHelper(web_state, password_manager)));
   }
 }
 
@@ -42,7 +42,7 @@
 
 AutofillTabHelper::AutofillTabHelper(
     web::WebState* web_state,
-    password_manager::PasswordGenerationManager* password_generation_manager)
+    password_manager::PasswordManager* password_manager)
     : browser_state_(ios::ChromeBrowserState::FromBrowserState(
           web_state->GetBrowserState())),
       autofill_agent_([[AutofillAgent alloc]
@@ -55,7 +55,7 @@
   DCHECK(infobar_manager);
   autofill_client_ = std::make_unique<autofill::ChromeAutofillClientIOS>(
       browser_state_, web_state, infobar_manager, autofill_agent_,
-      password_generation_manager);
+      password_manager);
 
   autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
       web_state, autofill_client_.get(), autofill_agent_,
diff --git a/ios/chrome/browser/ntp/new_tab_page_tab_helper.h b/ios/chrome/browser/ntp/new_tab_page_tab_helper.h
index 2dd7d31..64190844 100644
--- a/ios/chrome/browser/ntp/new_tab_page_tab_helper.h
+++ b/ios/chrome/browser/ntp/new_tab_page_tab_helper.h
@@ -15,6 +15,10 @@
 
 @protocol NewTabPageTabHelperDelegate;
 
+namespace web {
+class NavigationItem;
+}
+
 // NewTabPageTabHelper which manages a single NTP per tab.
 class NewTabPageTabHelper : public web::WebStateObserver,
                             public web::WebStateUserData<NewTabPageTabHelper> {
@@ -58,7 +62,7 @@
 
   // Sets the NTP's NavigationItem title and virtualURL to the appropriate
   // string and chrome://newtab respectively.
-  void UpdatePendingItem();
+  void UpdateItem(web::NavigationItem* item);
 
   // Returns true if an |url| is either chrome://newtab or about://newtab.
   bool IsNTPURL(const GURL& url);
diff --git a/ios/chrome/browser/ntp/new_tab_page_tab_helper.mm b/ios/chrome/browser/ntp/new_tab_page_tab_helper.mm
index 7dc646b..1f5bb72d 100644
--- a/ios/chrome/browser/ntp/new_tab_page_tab_helper.mm
+++ b/ios/chrome/browser/ntp/new_tab_page_tab_helper.mm
@@ -61,7 +61,7 @@
 
   active_ = IsNTPURL(web_state->GetVisibleURL());
   if (active_) {
-    UpdatePendingItem();
+    UpdateItem(web_state_->GetNavigationManager()->GetPendingItem());
     [delegate_ newTabPageHelperDidChangeVisibility:this forWebState:web_state_];
 
     // If about://newtab is currently loading but has not yet committed, block
@@ -120,7 +120,7 @@
     web::WebState* web_state,
     web::NavigationContext* navigation_context) {
   if (IsNTPURL(navigation_context->GetUrl())) {
-    UpdatePendingItem();
+    UpdateItem(web_state_->GetNavigationManager()->GetPendingItem());
   } else {
     SetActive(false);
   }
@@ -129,10 +129,12 @@
 void NewTabPageTabHelper::DidFinishNavigation(
     web::WebState* web_state,
     web::NavigationContext* navigation_context) {
-  if (navigation_context->IsSameDocument()) {
+  if (navigation_context->IsSameDocument() ||
+      !navigation_context->HasCommitted()) {
     return;
   }
 
+  UpdateItem(web_state_->GetNavigationManager()->GetLastCommittedItem());
   DisableIgnoreLoadRequests();
   SetActive(IsNTPURL(web_state->GetLastCommittedURL()));
 }
@@ -149,10 +151,8 @@
   }
 }
 
-void NewTabPageTabHelper::UpdatePendingItem() {
-  web::NavigationManager* manager = web_state_->GetNavigationManager();
-  web::NavigationItem* item = manager->GetPendingItem();
-  if (item) {
+void NewTabPageTabHelper::UpdateItem(web::NavigationItem* item) {
+  if (item && item->GetURL() == GURL(kChromeUIAboutNewTabURL)) {
     item->SetVirtualURL(GURL(kChromeUINewTabURL));
     item->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
   }
diff --git a/ios/chrome/browser/ntp/new_tab_page_tab_helper_unittest.mm b/ios/chrome/browser/ntp/new_tab_page_tab_helper_unittest.mm
index 039b920..6a59e9a 100644
--- a/ios/chrome/browser/ntp/new_tab_page_tab_helper_unittest.mm
+++ b/ios/chrome/browser/ntp/new_tab_page_tab_helper_unittest.mm
@@ -63,6 +63,7 @@
         std::make_unique<web::TestNavigationManager>();
     test_navigation_manager_ = test_navigation_manager.get();
     pending_item_ = web::NavigationItem::Create();
+    pending_item_->SetURL(GURL(kChromeUIAboutNewTabURL));
     test_navigation_manager->SetPendingItem(pending_item_.get());
     test_web_state_.SetNavigationManager(std::move(test_navigation_manager));
     test_web_state_.SetBrowserState(chrome_browser_state_.get());
@@ -138,6 +139,7 @@
   GURL url(kChromeUINewTabURL);
   test_web_state_.SetCurrentURL(url);
   web::FakeNavigationContext context;
+  context.SetHasCommitted(true);
   context.SetUrl(url);
   test_web_state_.OnNavigationFinished(&context);
   EXPECT_TRUE(tab_helper()->IsActive());
@@ -162,3 +164,28 @@
   test_web_state_.OnNavigationFinished(&context);
   EXPECT_FALSE(tab_helper()->IsActive());
 }
+
+// Tests double navigations from an NTP and non-NTP page at the same time.
+TEST_F(NewTabPageTabHelperTest, TestMismatchedPendingItem) {
+  base::test::ScopedFeatureList scoped_feature_list_;
+  scoped_feature_list_.InitAndEnableFeature(kBrowserContainerContainsNTP);
+
+  // Test an NTP url with a mismatched pending item.
+  GURL url(kChromeUINewTabURL);
+  GURL not_ntp_url(kTestURL);
+  test_web_state_.SetCurrentURL(url);
+  pending_item_->SetURL(not_ntp_url);
+  CreateTabHelper();
+  // In this edge case, although the NTP is visible, the pending item is not
+  // incorrectly updated
+  EXPECT_EQ(GURL(kTestURL), pending_item_->GetVirtualURL());
+
+  // On commit, the web state url is correct, and the NTP is inactive.
+  web::FakeNavigationContext context;
+  context.SetHasCommitted(true);
+  context.SetUrl(not_ntp_url);
+  test_web_state_.SetCurrentURL(not_ntp_url);
+  test_web_state_.OnNavigationFinished(&context);
+  EXPECT_FALSE(tab_helper()->IsActive());
+  EXPECT_EQ(GURL(kTestURL), pending_item_->GetVirtualURL());
+}
diff --git a/ios/chrome/browser/passwords/password_tab_helper.h b/ios/chrome/browser/passwords/password_tab_helper.h
index d4d38ba3..02d5f9d3 100644
--- a/ios/chrome/browser/passwords/password_tab_helper.h
+++ b/ios/chrome/browser/passwords/password_tab_helper.h
@@ -19,6 +19,7 @@
 
 namespace password_manager {
 class PasswordGenerationManager;
+class PasswordManager;
 }
 
 // Class binding a PasswordController to a WebState.
@@ -55,6 +56,9 @@
   // Returns the PasswordGenerationManager owned by the PasswordController.
   password_manager::PasswordGenerationManager* GetPasswordGenerationManager();
 
+  // Returns the PasswordManager owned by the PasswordController.
+  password_manager::PasswordManager* GetPasswordManager();
+
  private:
   friend class web::WebStateUserData<PasswordTabHelper>;
 
diff --git a/ios/chrome/browser/passwords/password_tab_helper.mm b/ios/chrome/browser/passwords/password_tab_helper.mm
index a9fae3d..11f0355 100644
--- a/ios/chrome/browser/passwords/password_tab_helper.mm
+++ b/ios/chrome/browser/passwords/password_tab_helper.mm
@@ -60,6 +60,10 @@
   return controller_.passwordGenerationManager;
 }
 
+password_manager::PasswordManager* PasswordTabHelper::GetPasswordManager() {
+  return controller_.passwordManager;
+}
+
 PasswordTabHelper::PasswordTabHelper(web::WebState* web_state)
     : controller_([[PasswordController alloc] initWithWebState:web_state]) {
   web_state->AddObserver(this);
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index db87f14..e23b5874 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -122,8 +122,8 @@
   PasswordTabHelper::CreateForWebState(web_state);
 
   AutofillTabHelper::CreateForWebState(
-      web_state, PasswordTabHelper::FromWebState(web_state)
-                     ->GetPasswordGenerationManager());
+      web_state,
+      PasswordTabHelper::FromWebState(web_state)->GetPasswordManager());
 
   // Depends on favicon::WebFaviconDriver, must be created after it.
   if (base::FeatureList::IsEnabled(kCustomSearchEngines)) {
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
index 98e1345..b14db696 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -21,7 +21,7 @@
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #import "components/autofill/ios/browser/autofill_client_ios_bridge.h"
 #include "components/infobars/core/infobar_manager.h"
-#include "components/password_manager/core/browser/password_generation_manager.h"
+#include "components/password_manager/core/browser/password_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/driver/sync_service.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -34,12 +34,11 @@
 // Chrome iOS implementation of AutofillClient.
 class ChromeAutofillClientIOS : public AutofillClient {
  public:
-  ChromeAutofillClientIOS(
-      ios::ChromeBrowserState* browser_state,
-      web::WebState* web_state,
-      infobars::InfoBarManager* infobar_manager,
-      id<AutofillClientIOSBridge> bridge,
-      password_manager::PasswordGenerationManager* password_generation_manager);
+  ChromeAutofillClientIOS(ios::ChromeBrowserState* browser_state,
+                          web::WebState* web_state,
+                          infobars::InfoBarManager* infobar_manager,
+                          id<AutofillClientIOSBridge> bridge,
+                          password_manager::PasswordManager* password_manager);
   ~ChromeAutofillClientIOS() override;
 
   // Sets a weak reference to the view controller used to present UI.
@@ -132,7 +131,7 @@
   std::unique_ptr<FormDataImporter> form_data_importer_;
   scoped_refptr<AutofillWebDataService> autofill_web_data_service_;
   infobars::InfoBarManager* infobar_manager_;
-  password_manager::PasswordGenerationManager* password_generation_manager_;
+  password_manager::PasswordManager* password_manager_;
   CardUnmaskPromptControllerImpl unmask_controller_;
 
   // A weak reference to the view controller used to present UI.
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
index 050b642..b3bedae0 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -66,7 +66,7 @@
     web::WebState* web_state,
     infobars::InfoBarManager* infobar_manager,
     id<AutofillClientIOSBridge> bridge,
-    password_manager::PasswordGenerationManager* password_generation_manager)
+    password_manager::PasswordManager* password_manager)
     : pref_service_(browser_state->GetPrefs()),
       sync_service_(
           ProfileSyncServiceFactory::GetForBrowserState(browser_state)),
@@ -92,7 +92,7 @@
           personal_data_manager_,
           GetApplicationContext()->GetApplicationLocale())),
       infobar_manager_(infobar_manager),
-      password_generation_manager_(password_generation_manager),
+      password_manager_(password_manager),
       unmask_controller_(browser_state->GetPrefs(),
                          browser_state->IsOffTheRecord()) {}
 
@@ -319,9 +319,7 @@
 void ChromeAutofillClientIOS::PropagateAutofillPredictions(
     content::RenderFrameHost* rfh,
     const std::vector<FormStructure*>& forms) {
-  if (password_generation_manager_) {
-    password_generation_manager_->DetectFormsEligibleForGeneration(forms);
-  }
+  password_manager_->ProcessAutofillPredictions(/*driver=*/nullptr, forms);
 }
 
 void ChromeAutofillClientIOS::DidFillOrPreviewField(
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h
index 140deb9..07e62f5 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h
@@ -13,7 +13,7 @@
 // TableViewTextItem contains the model data for a TableViewTextCell.
 @interface TableViewTextItem : TableViewItem
 
-// Text Alignment for the cell's textLabel. Default is NSTextAlignmentLeft.
+// Text Alignment for the cell's textLabel. Default is NSTextAlignmentNatural.
 @property(nonatomic, assign) NSTextAlignment textAlignment;
 
 // UIColor for the cell's textLabel. Default is
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm
index 558d546a..8d3ab38 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm
@@ -66,7 +66,7 @@
         UIColorFromRGB(kTableViewTextLabelColorLightGrey);
   }
   cell.textLabel.textAlignment =
-      self.textAlignment ? self.textAlignment : NSTextAlignmentLeft;
+      self.textAlignment ? self.textAlignment : NSTextAlignmentNatural;
 
   cell.userInteractionEnabled = self.enabled;
 }
diff --git a/ios/net/cookies/cookie_store_ios_test_util.h b/ios/net/cookies/cookie_store_ios_test_util.h
index 4c71e8a..74c51e4 100644
--- a/ios/net/cookies/cookie_store_ios_test_util.h
+++ b/ios/net/cookies/cookie_store_ios_test_util.h
@@ -44,7 +44,7 @@
   void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
   void DeleteCookie(const net::CanonicalCookie& cc) override;
   void SetForceKeepSessionState() override;
-  void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
+  void SetBeforeCommitCallback(base::RepeatingClosure callback) override;
   void Flush(base::OnceClosure callback) override;
 
   ~TestPersistentCookieStore() override;
diff --git a/ios/net/cookies/cookie_store_ios_test_util.mm b/ios/net/cookies/cookie_store_ios_test_util.mm
index 426c0527..a0ef382 100644
--- a/ios/net/cookies/cookie_store_ios_test_util.mm
+++ b/ios/net/cookies/cookie_store_ios_test_util.mm
@@ -84,7 +84,7 @@
 
 void TestPersistentCookieStore::SetForceKeepSessionState() {}
 
-void TestPersistentCookieStore::SetBeforeFlushCallback(
+void TestPersistentCookieStore::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {}
 
 void TestPersistentCookieStore::Flush(base::OnceClosure callback) {
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index 2e10ae7f..4cb3722 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -170,7 +170,7 @@
     deps = [
       ":media_java_resources",
       "//base:base_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
     srcjar_deps = [
       ":java_enums",
diff --git a/media/capture/video/android/BUILD.gn b/media/capture/video/android/BUILD.gn
index 046b646..1148a14e 100644
--- a/media/capture/video/android/BUILD.gn
+++ b/media/capture/video/android/BUILD.gn
@@ -52,7 +52,7 @@
 android_library("capture_java") {
   deps = [
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
 
   srcjar_deps = [ ":media_java_enums_srcjar" ]
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc
index 3b8d96e..127e7da 100644
--- a/media/renderers/video_resource_updater.cc
+++ b/media/renderers/video_resource_updater.cc
@@ -479,6 +479,7 @@
                                        gfx::Transform transform,
                                        gfx::Rect quad_rect,
                                        gfx::Rect visible_quad_rect,
+                                       const gfx::RRectF& rounded_corner_bounds,
                                        gfx::Rect clip_rect,
                                        bool is_clipped,
                                        bool contents_opaque,
@@ -488,8 +489,9 @@
 
   viz::SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(transform, quad_rect, visible_quad_rect, clip_rect,
-                            is_clipped, contents_opaque, draw_opacity,
+  shared_quad_state->SetAll(transform, quad_rect, visible_quad_rect,
+                            rounded_corner_bounds, clip_rect, is_clipped,
+                            contents_opaque, draw_opacity,
                             SkBlendMode::kSrcOver, sorting_context_id);
 
   bool needs_blending = !contents_opaque;
diff --git a/media/renderers/video_resource_updater.h b/media/renderers/video_resource_updater.h
index 39c3ed8..634c1ad9 100644
--- a/media/renderers/video_resource_updater.h
+++ b/media/renderers/video_resource_updater.h
@@ -27,6 +27,7 @@
 
 namespace gfx {
 class Rect;
+class RRectF;
 class Transform;
 }  // namespace gfx
 
@@ -109,6 +110,7 @@
                    gfx::Transform transform,
                    gfx::Rect quad_rect,
                    gfx::Rect visible_quad_rect,
+                   const gfx::RRectF& rounded_corner_bounds,
                    gfx::Rect clip_rect,
                    bool is_clipped,
                    bool context_opaque,
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn
index d0640ac..5ec8814c 100644
--- a/net/android/BUILD.gn
+++ b/net/android/BUILD.gn
@@ -28,7 +28,7 @@
   deps = [
     ":net_thread_stats_uid_java",
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/jsr-305:jsr_305_javalib",
   ]
   srcjar_deps = [
@@ -52,7 +52,7 @@
 android_library("embedded_test_server_aidl_java") {
   testonly = true
   deps = [
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   srcjar_deps = [ ":embedded_test_server_aidl" ]
 }
@@ -72,7 +72,7 @@
     ":net_java",
     "//base:base_java",
     "//base:base_java_test_support",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index 83f285e..d96e904a 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -377,7 +377,7 @@
     // CookieMonster. To avoid the PersistentCookieStore retaining a pointer to
     // the ChannelIDStore via this callback after this CookieMonster is
     // destroyed, CookieMonster's d'tor sets the callback to a null callback.
-    store_->SetBeforeFlushCallback(
+    store_->SetBeforeCommitCallback(
         base::Bind(&ChannelIDStore::Flush,
                    base::Unretained(channel_id_service_->GetChannelIDStore())));
   }
@@ -585,7 +585,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (channel_id_service_ && store_) {
-    store_->SetBeforeFlushCallback(base::Closure());
+    store_->SetBeforeCommitCallback(base::RepeatingClosure());
   }
 
   // TODO(mmenke): Does it really make sense to run
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index b9aeaaf..d92c94b 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -683,7 +683,7 @@
   // Sets a callback that will be run before the store flushes.  If |callback|
   // performs any async operations, the store will not wait for those to finish
   // before flushing.
-  virtual void SetBeforeFlushCallback(base::RepeatingClosure callback) = 0;
+  virtual void SetBeforeCommitCallback(base::RepeatingClosure callback) = 0;
 
   // Flushes the store and posts |callback| when complete. |callback| may be
   // NULL.
diff --git a/net/cookies/cookie_monster_store_test.cc b/net/cookies/cookie_monster_store_test.cc
index d31091b9..c929043 100644
--- a/net/cookies/cookie_monster_store_test.cc
+++ b/net/cookies/cookie_monster_store_test.cc
@@ -89,7 +89,7 @@
 
 void MockPersistentCookieStore::SetForceKeepSessionState() {}
 
-void MockPersistentCookieStore::SetBeforeFlushCallback(
+void MockPersistentCookieStore::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {}
 
 void MockPersistentCookieStore::Flush(base::OnceClosure callback) {
@@ -186,7 +186,7 @@
 
 void MockSimplePersistentCookieStore::SetForceKeepSessionState() {}
 
-void MockSimplePersistentCookieStore::SetBeforeFlushCallback(
+void MockSimplePersistentCookieStore::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {}
 
 void MockSimplePersistentCookieStore::Flush(base::OnceClosure callback) {
diff --git a/net/cookies/cookie_monster_store_test.h b/net/cookies/cookie_monster_store_test.h
index cc8b25a28..c85c0eb 100644
--- a/net/cookies/cookie_monster_store_test.h
+++ b/net/cookies/cookie_monster_store_test.h
@@ -104,7 +104,7 @@
 
   void SetForceKeepSessionState() override;
 
-  void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
+  void SetBeforeCommitCallback(base::RepeatingClosure callback) override;
 
   void Flush(base::OnceClosure callback) override;
 
@@ -159,7 +159,7 @@
 
   void SetForceKeepSessionState() override;
 
-  void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
+  void SetBeforeCommitCallback(base::RepeatingClosure callback) override;
 
   void Flush(base::OnceClosure callback) override;
 
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index b4c354c..02521262 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -71,7 +71,7 @@
   MOCK_METHOD1(AddCookie, void(const CanonicalCookie& cc));
   MOCK_METHOD1(UpdateCookieAccessTime, void(const CanonicalCookie& cc));
   MOCK_METHOD1(DeleteCookie, void(const CanonicalCookie& cc));
-  MOCK_METHOD1(SetBeforeFlushCallback, void(base::RepeatingClosure));
+  MOCK_METHOD1(SetBeforeCommitCallback, void(base::RepeatingClosure));
   void Flush(base::OnceClosure callback) override {
     if (!callback.is_null())
       base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
@@ -2561,15 +2561,15 @@
   ASSERT_EQ(3, counter->callback_count());
 }
 
-TEST_F(CookieMonsterTest, SetBeforeFlushCallbackIsCalled) {
+TEST_F(CookieMonsterTest, SetBeforeCommitCallbackIsCalled) {
   std::unique_ptr<ChannelIDService> channel_id_service(
       new ChannelIDService(nullptr));
 
   scoped_refptr<NewMockPersistentCookieStore> store(
       new NewMockPersistentCookieStore());
 
-  // SetBeforeFlushCallback should be called in both the c'tor and d'tor.
-  EXPECT_CALL(*store, SetBeforeFlushCallback(testing::_)).Times(2);
+  // SetBeforeCommitCallback should be called in both the c'tor and d'tor.
+  EXPECT_CALL(*store, SetBeforeCommitCallback(testing::_)).Times(2);
 
   std::unique_ptr<CookieMonster> cm(
       new CookieMonster(store.get(), channel_id_service.get(), &net_log_));
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc
index 047082f..70675bc1 100644
--- a/net/cookies/cookie_store_test_helpers.cc
+++ b/net/cookies/cookie_store_test_helpers.cc
@@ -245,7 +245,7 @@
 
 void FlushablePersistentStore::SetForceKeepSessionState() {}
 
-void FlushablePersistentStore::SetBeforeFlushCallback(
+void FlushablePersistentStore::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {}
 
 void FlushablePersistentStore::Flush(base::OnceClosure callback) {
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h
index 85935fa..28fc2c34 100644
--- a/net/cookies/cookie_store_test_helpers.h
+++ b/net/cookies/cookie_store_test_helpers.h
@@ -156,7 +156,7 @@
   void UpdateCookieAccessTime(const CanonicalCookie&) override;
   void DeleteCookie(const CanonicalCookie&) override;
   void SetForceKeepSessionState() override;
-  void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
+  void SetBeforeCommitCallback(base::RepeatingClosure callback) override;
   void Flush(base::OnceClosure callback) override;
 
   int flush_count();
diff --git a/net/disk_cache/blockfile/entry_impl.cc b/net/disk_cache/blockfile/entry_impl.cc
index dc96b82..dcbb28ac 100644
--- a/net/disk_cache/blockfile/entry_impl.cc
+++ b/net/disk_cache/blockfile/entry_impl.cc
@@ -8,6 +8,7 @@
 
 #include "base/hash.h"
 #include "base/macros.h"
+#include "base/numerics/safe_math.h"
 #include "base/strings/string_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -1034,7 +1035,9 @@
 
   TimeTicks start = TimeTicks::Now();
 
-  if (offset + buf_len > entry_size)
+  int end_offset;
+  if (!base::CheckAdd(offset, buf_len).AssignIfValid(&end_offset) ||
+      end_offset > entry_size)
     buf_len = entry_size - offset;
 
   UpdateRank(false);
@@ -1120,12 +1123,12 @@
 
   int max_file_size = backend_->MaxFileSize();
 
-  // offset or buf_len could be negative numbers.
+  int end_offset;
   if (offset > max_file_size || buf_len > max_file_size ||
-      offset + buf_len > max_file_size) {
-    int size = offset + buf_len;
-    if (size <= max_file_size)
-      size = std::numeric_limits<int32_t>::max();
+      !base::CheckAdd(offset, buf_len).AssignIfValid(&end_offset) ||
+      end_offset > max_file_size) {
+    int size = base::CheckAdd(offset, buf_len)
+                   .ValueOrDefault(std::numeric_limits<int32_t>::max());
     backend_->TooMuchStorageRequested(size);
     return net::ERR_FAILED;
   }
diff --git a/net/disk_cache/memory/mem_entry_impl.cc b/net/disk_cache/memory/mem_entry_impl.cc
index 74d28467..d329623 100644
--- a/net/disk_cache/memory/mem_entry_impl.cc
+++ b/net/disk_cache/memory/mem_entry_impl.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_math.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "net/base/interval.h"
@@ -359,7 +360,9 @@
   if (offset >= entry_size || offset < 0 || !buf_len)
     return 0;
 
-  if (offset + buf_len > entry_size)
+  int end_offset;
+  if (!base::CheckAdd(offset, buf_len).AssignIfValid(&end_offset) ||
+      end_offset > entry_size)
     buf_len = entry_size - offset;
 
   UpdateStateOnUse(ENTRY_WAS_NOT_MODIFIED);
@@ -390,16 +393,17 @@
 
   int max_file_size = backend_->MaxFileSize();
 
-  // offset of buf_len could be negative numbers.
+  int end_offset;
   if (offset > max_file_size || buf_len > max_file_size ||
-      offset + buf_len > max_file_size) {
+      !base::CheckAdd(offset, buf_len).AssignIfValid(&end_offset) ||
+      end_offset > max_file_size) {
     RecordWriteResult(MEM_ENTRY_WRITE_RESULT_OVER_MAX_ENTRY_SIZE);
     return net::ERR_FAILED;
   }
 
   int old_data_size = data_[index].size();
-  if (truncate || old_data_size < offset + buf_len) {
-    int delta = offset + buf_len - old_data_size;
+  if (truncate || old_data_size < end_offset) {
+    int delta = end_offset - old_data_size;
     backend_->ModifyStorageSize(delta);
     if (backend_->HasExceededStorageSize()) {
       backend_->ModifyStorageSize(-delta);
@@ -407,7 +411,7 @@
       return net::ERR_INSUFFICIENT_RESOURCES;
     }
 
-    data_[index].resize(offset + buf_len);
+    data_[index].resize(end_offset);
 
     // Zero fill any hole.
     if (old_data_size < offset) {
@@ -434,7 +438,9 @@
   if (!InitSparseInfo())
     return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
 
-  if (offset < 0 || buf_len < 0)
+  // Check that offset + buf_len does not overflow. This ensures that
+  // offset + io_buf->BytesConsumed() never overflows below.
+  if (offset < 0 || buf_len < 0 || !base::CheckAdd(offset, buf_len).IsValid())
     return net::ERR_INVALID_ARGUMENT;
 
   // We will keep using this buffer and adjust the offset in this buffer.
@@ -497,7 +503,9 @@
   if (!backend_)
     return net::ERR_FAILED;
 
-  if (offset < 0 || buf_len < 0)
+  // Check that offset + buf_len does not overflow. This ensures that
+  // offset + io_buf->BytesConsumed() never overflows below.
+  if (offset < 0 || buf_len < 0 || !base::CheckAdd(offset, buf_len).IsValid())
     return net::ERR_INVALID_ARGUMENT;
 
   scoped_refptr<net::DrainableIOBuffer> io_buf =
@@ -566,6 +574,7 @@
   if (offset < 0 || len < 0 || !start)
     return net::ERR_INVALID_ARGUMENT;
 
+  // If offset + len overflows, this will just be the empty interval.
   net::Interval<int64_t> requested(offset, offset + len);
 
   // Find the first relevant child, if any --- may have to skip over
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index 75a1285..ee55cd5 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -474,7 +474,9 @@
     RecordWriteResult(cache_type_, SIMPLE_ENTRY_WRITE_RESULT_INVALID_ARGUMENT);
     return net::ERR_INVALID_ARGUMENT;
   }
-  if (backend_.get() && offset + buf_len > backend_->MaxFileSize()) {
+  int end_offset;
+  if (!base::CheckAdd(offset, buf_len).AssignIfValid(&end_offset) ||
+      (backend_.get() && end_offset > backend_->MaxFileSize())) {
     if (net_log_.IsCapturing()) {
       net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_WRITE_END,
                         CreateNetLogReadWriteCompleteCallback(net::ERR_FAILED));
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index 3ce539c..74d7045 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -800,10 +800,18 @@
     return;
   }
 
-  uint64_t sparse_data_size = out_entry_stat->sparse_data_size();
+  int32_t sparse_data_size = out_entry_stat->sparse_data_size();
+  int32_t future_sparse_data_size;
+  if (!base::CheckAdd(sparse_data_size, buf_len)
+           .AssignIfValid(&future_sparse_data_size) ||
+      future_sparse_data_size < 0) {
+    Doom();
+    *out_result = net::ERR_CACHE_WRITE_FAILURE;
+    return;
+  }
   // This is a pessimistic estimate; it assumes the entire buffer is going to
   // be appended as a new range, not written over existing ranges.
-  if (sparse_data_size + buf_len > max_sparse_data_size) {
+  if (static_cast<uint64_t>(future_sparse_data_size) > max_sparse_data_size) {
     DVLOG(1) << "Truncating sparse data file (" << sparse_data_size << " + "
              << buf_len << " > " << max_sparse_data_size << ")";
     TruncateSparseFile(sparse_file.get());
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index 4438f44..9959f9f 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -1486,9 +1486,9 @@
   // This store never discards session-only cookies, so this call has no effect.
 }
 
-void SQLitePersistentCookieStore::SetBeforeFlushCallback(
+void SQLitePersistentCookieStore::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {
-  backend_->SetBeforeFlushCallback(std::move(callback));
+  backend_->SetBeforeCommitCallback(std::move(callback));
 }
 
 void SQLitePersistentCookieStore::Flush(base::OnceClosure callback) {
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.h b/net/extras/sqlite/sqlite_persistent_cookie_store.h
index 7ea56e2..5322f6f 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store.h
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store.h
@@ -63,7 +63,7 @@
   void UpdateCookieAccessTime(const CanonicalCookie& cc) override;
   void DeleteCookie(const CanonicalCookie& cc) override;
   void SetForceKeepSessionState() override;
-  void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
+  void SetBeforeCommitCallback(base::RepeatingClosure callback) override;
   void Flush(base::OnceClosure callback) override;
 
   // Returns how many operations are currently queued. For test use only;
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 656faf6c..0043b78d 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -466,7 +466,7 @@
                              NetLogEventPhase::NONE);
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, TestBeforeFlushCallback) {
+TEST_F(SQLitePersistentCookieStoreTest, TestBeforeCommitCallback) {
   InitializeStore(false, false);
 
   struct Counter {
@@ -475,8 +475,8 @@
   };
 
   Counter counter;
-  store_->SetBeforeFlushCallback(
-      base::Bind(&Counter::increment, base::Unretained(&counter)));
+  store_->SetBeforeCommitCallback(
+      base::BindRepeating(&Counter::increment, base::Unretained(&counter)));
 
   // The implementation of SQLitePersistentCookieStore::Backend flushes changes
   // after 30s or 512 pending operations. Add 512 cookies to the store to test
diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
index 8437a06c..805d5ee9 100644
--- a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
+++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
@@ -58,10 +58,10 @@
   }
 }
 
-void SQLitePersistentStoreBackendBase::SetBeforeFlushCallback(
+void SQLitePersistentStoreBackendBase::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {
-  base::AutoLock locked(before_flush_callback_lock_);
-  before_flush_callback_ = std::move(callback);
+  base::AutoLock locked(before_commit_callback_lock_);
+  before_commit_callback_ = std::move(callback);
 }
 
 bool SQLitePersistentStoreBackendBase::InitializeDatabase() {
@@ -149,9 +149,9 @@
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   {
-    base::AutoLock locked(before_flush_callback_lock_);
-    if (!before_flush_callback_.is_null())
-      before_flush_callback_.Run();
+    base::AutoLock locked(before_commit_callback_lock_);
+    if (!before_commit_callback_.is_null())
+      before_commit_callback_.Run();
   }
 
   DoCommit();
diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.h b/net/extras/sqlite/sqlite_persistent_store_backend_base.h
index 7e29bed..f9d9306 100644
--- a/net/extras/sqlite/sqlite_persistent_store_backend_base.h
+++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.h
@@ -59,7 +59,7 @@
   void Close();
 
   // Set the callback that will be run at the beginning of Commit.
-  void SetBeforeFlushCallback(base::RepeatingClosure callback);
+  void SetBeforeCommitCallback(base::RepeatingClosure callback);
 
  protected:
   friend class base::RefCountedThreadSafe<SQLitePersistentStoreBackendBase>;
@@ -116,7 +116,7 @@
   void Reset();
 
   // Commit pending operations to the database. First runs
-  // |before_flush_callback_|. Should be called on the background thread.
+  // |before_commit_callback_|. Should be called on the background thread.
   void Commit();
 
   // Embedder-specific logic to commit pending operations. (This base class has
@@ -186,10 +186,10 @@
   const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
 
   // Callback to be run before Commit.
-  base::RepeatingClosure before_flush_callback_
-      GUARDED_BY(before_flush_callback_lock_);
-  // Guards |before_flush_callback_|.
-  base::Lock before_flush_callback_lock_;
+  base::RepeatingClosure before_commit_callback_
+      GUARDED_BY(before_commit_callback_lock_);
+  // Guards |before_commit_callback_|.
+  base::Lock before_commit_callback_lock_;
 
   DISALLOW_COPY_AND_ASSIGN(SQLitePersistentStoreBackendBase);
 };
diff --git a/net/filter/gzip_source_stream_fuzzer.cc b/net/filter/gzip_source_stream_fuzzer.cc
index a7cbbadb..1fde1d8a 100644
--- a/net/filter/gzip_source_stream_fuzzer.cc
+++ b/net/filter/gzip_source_stream_fuzzer.cc
@@ -24,10 +24,9 @@
 
   // Gzip has a maximum compression ratio of 1032x. While, strictly speaking,
   // linear, this means the fuzzer will often get stuck. Stop reading at a more
-  // modest compression ratio of 10x, or 2 MiB, whichever is larger. See
+  // modest compression ratio of 2x, or 512 KiB, whichever is larger. See
   // https://crbug.com/921075.
-  size_t max_output =
-      std::max(10u * size, static_cast<size_t>(2 * 1024 * 1024));
+  size_t max_output = std::max(2u * size, static_cast<size_t>(512 * 1024));
 
   const net::SourceStream::SourceType kGzipTypes[] = {
       net::SourceStream::TYPE_GZIP, net::SourceStream::TYPE_DEFLATE};
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc
index 45c246b..74395cf 100644
--- a/net/url_request/redirect_info.cc
+++ b/net/url_request/redirect_info.cc
@@ -125,8 +125,7 @@
     const GURL& new_location,
     const base::Optional<std::string>& referrer_policy_header,
     bool insecure_scheme_was_upgraded,
-    bool copy_fragment,
-    bool is_signed_exchange_fallback_redirect) {
+    bool copy_fragment) {
   RedirectInfo redirect_info;
 
   redirect_info.status_code = http_status_code;
@@ -150,8 +149,6 @@
   }
 
   redirect_info.insecure_scheme_was_upgraded = insecure_scheme_was_upgraded;
-  redirect_info.is_signed_exchange_fallback_redirect =
-      is_signed_exchange_fallback_redirect;
 
   // Update the first-party URL if appropriate.
   if (original_first_party_url_policy ==
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h
index 524adf95..7236455 100644
--- a/net/url_request/redirect_info.h
+++ b/net/url_request/redirect_info.h
@@ -44,9 +44,7 @@
       // by default. Set false only when the network delegate has set the
       // desired redirect URL (with or without fragment), so it must not be
       // changed any more.
-      bool copy_fragment = true,
-      // Whether the redirect is caused by a failure of signed exchange loading.
-      bool is_signed_exchange_fallback_redirect = false);
+      bool copy_fragment = true);
 
   // The status code for the redirect response. This is almost redundant with
   // the response headers, but some URLRequestJobs emit redirects without
@@ -72,9 +70,6 @@
   // upgrade-insecure-requests policy.
   bool insecure_scheme_was_upgraded;
 
-  // True if this is a redirect from Signed Exchange to its fallback URL.
-  bool is_signed_exchange_fallback_redirect;
-
   // The new referrer policy that should be obeyed if there are
   // subsequent redirects.
   URLRequest::ReferrerPolicy new_referrer_policy;
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index b9b45dcf..628fd6d 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -254,7 +254,7 @@
     fuzzer_test("pdf_formcalc_context_fuzzer") {
       sources = []
       deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_formcalc_fuzzer_src",
+        "//third_party/pdfium/testing/fuzzers:pdf_formcalc_context_fuzzer_src",
       ]
       dict = "dicts/pdf_xfa_js.dict"
     }
diff --git a/remoting/android/client_java_tmpl.gni b/remoting/android/client_java_tmpl.gni
index 33f82da8..6a1db68e 100644
--- a/remoting/android/client_java_tmpl.gni
+++ b/remoting/android/client_java_tmpl.gni
@@ -82,9 +82,9 @@
       "//remoting/android:remoting_android_client_java_resources",
       "//remoting/android:remoting_apk_manifest",
       "//third_party/android_deps:android_arch_lifecycle_common_java",
-      "//third_party/android_deps:android_support_annotations_java",
       "//third_party/android_deps:android_support_v7_appcompat_java",
-      "//third_party/android_deps:android_support_v7_mediarouter_java",
+      "//third_party/android_deps:com_android_support_mediarouter_v7_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
       "//ui/android:ui_utils_java",
     ]
 
diff --git a/services/BUILD.gn b/services/BUILD.gn
index 334b054b..094989d 100644
--- a/services/BUILD.gn
+++ b/services/BUILD.gn
@@ -118,7 +118,7 @@
       "//services/device/public/mojom:mojom_java",
       "//services/shape_detection:shape_detection_java",
       "//skia/public/interfaces:interfaces_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
   }
 
diff --git a/services/metrics/public/cpp/metrics_utils_unittest.cc b/services/metrics/public/cpp/metrics_utils_unittest.cc
index 27cdca32..2176f3f 100644
--- a/services/metrics/public/cpp/metrics_utils_unittest.cc
+++ b/services/metrics/public/cpp/metrics_utils_unittest.cc
@@ -61,3 +61,31 @@
         << " with bucket_size: " << test.bucket_size;
   }
 }
+
+TEST(MetricsUtilsTest, GetExponentialBucketMinForUserTiming) {
+  struct {
+    int64_t expected_result;
+    int64_t sample;
+  } int_test_cases[] = {
+      // Typical positive cases.
+      {1, 1},
+      {32, 38},
+      {32, 51},
+      {64, 99},
+      {16, 25},
+      {512, 1023},
+      {1024, 1024},
+      {1024, 1025},
+      // Negative samples.
+      {0, -45},
+      // Zero samples.
+      {0, 0},
+  };
+
+  // Test int64_t sample cases.
+  for (const auto& test : int_test_cases) {
+    EXPECT_EQ(test.expected_result,
+              ukm::GetExponentialBucketMinForUserTiming(test.sample))
+        << "For sample: " << test.sample;
+  }
+}
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index dd858f0..20b30833 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -125,8 +125,6 @@
     "resource_scheduler_params_manager.h",
     "restricted_cookie_manager.cc",
     "restricted_cookie_manager.h",
-    "session_cleanup_channel_id_store.cc",
-    "session_cleanup_channel_id_store.h",
     "session_cleanup_cookie_store.cc",
     "session_cleanup_cookie_store.h",
     "socket_data_pump.cc",
@@ -319,7 +317,6 @@
     "resource_scheduler_params_manager_unittest.cc",
     "resource_scheduler_unittest.cc",
     "restricted_cookie_manager_unittest.cc",
-    "session_cleanup_channel_id_store_unittest.cc",
     "session_cleanup_cookie_store_unittest.cc",
     "socket_data_pump_unittest.cc",
     "ssl_config_service_mojo_unittest.cc",
diff --git a/services/network/cookie_manager.cc b/services/network/cookie_manager.cc
index 0c7ce77a..8c792e5 100644
--- a/services/network/cookie_manager.cc
+++ b/services/network/cookie_manager.cc
@@ -15,7 +15,6 @@
 #include "net/cookies/cookie_store.h"
 #include "net/cookies/cookie_util.h"
 #include "services/network/cookie_managers_shared.h"
-#include "services/network/session_cleanup_channel_id_store.h"
 #include "services/network/session_cleanup_cookie_store.h"
 #include "url/gurl.h"
 
@@ -54,13 +53,9 @@
 CookieManager::CookieManager(
     net::CookieStore* cookie_store,
     scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store,
-    scoped_refptr<SessionCleanupChannelIDStore>
-        session_cleanup_channel_id_store,
     mojom::CookieManagerParamsPtr params)
     : cookie_store_(cookie_store),
-      session_cleanup_cookie_store_(std::move(session_cleanup_cookie_store)),
-      session_cleanup_channel_id_store_(
-          std::move(session_cleanup_channel_id_store)) {
+      session_cleanup_cookie_store_(std::move(session_cleanup_cookie_store)) {
   if (params) {
     cookie_settings_.set_block_third_party_cookies(
         params->block_third_party_cookies);
@@ -79,11 +74,6 @@
     session_cleanup_cookie_store_->DeleteSessionCookies(
         cookie_settings_.CreateDeleteCookieOnExitPredicate());
   }
-  if (session_cleanup_channel_id_store_) {
-    session_cleanup_channel_id_store_->DeleteSessionChannelIDs(
-        base::BindRepeating(&CookieSettings::IsCookieSessionOnly,
-                            base::Unretained(&cookie_settings_)));
-  }
 }
 
 void CookieManager::AddRequest(mojom::CookieManagerRequest request) {
@@ -221,8 +211,6 @@
 
 void CookieManager::SetForceKeepSessionState() {
   cookie_store_->SetForceKeepSessionState();
-  if (session_cleanup_channel_id_store_)
-    session_cleanup_channel_id_store_->SetForceKeepSessionState();
 }
 
 void CookieManager::BlockThirdPartyCookies(bool block) {
diff --git a/services/network/cookie_manager.h b/services/network/cookie_manager.h
index 9f19832e..6cef8ce 100644
--- a/services/network/cookie_manager.h
+++ b/services/network/cookie_manager.h
@@ -26,7 +26,6 @@
 
 namespace network {
 class SessionCleanupCookieStore;
-class SessionCleanupChannelIDStore;
 
 // Wrap a cookie store in an implementation of the mojo cookie interface.
 
@@ -41,8 +40,6 @@
   CookieManager(
       net::CookieStore* cookie_store,
       scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store,
-      scoped_refptr<SessionCleanupChannelIDStore>
-          session_cleanup_channel_id_store,
       mojom::CookieManagerParamsPtr params);
 
   ~CookieManager() override;
@@ -111,7 +108,6 @@
 
   net::CookieStore* const cookie_store_;
   scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store_;
-  scoped_refptr<SessionCleanupChannelIDStore> session_cleanup_channel_id_store_;
   mojo::BindingSet<mojom::CookieManager> bindings_;
   std::vector<std::unique_ptr<ListenerRegistration>> listener_registrations_;
   // Note: RestrictedCookieManager stores pointers to |cookie_settings_|.
diff --git a/services/network/cookie_manager_unittest.cc b/services/network/cookie_manager_unittest.cc
index 5b3afe6..53a0cbb 100644
--- a/services/network/cookie_manager_unittest.cc
+++ b/services/network/cookie_manager_unittest.cc
@@ -23,7 +23,6 @@
 #include "net/cookies/cookie_store_test_callbacks.h"
 #include "net/cookies/cookie_store_test_helpers.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
-#include "services/network/session_cleanup_channel_id_store.h"
 #include "services/network/session_cleanup_cookie_store.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -172,7 +171,7 @@
 
 class CookieManagerTest : public testing::Test {
  public:
-  CookieManagerTest() { InitializeCookieService(nullptr, nullptr, nullptr); }
+  CookieManagerTest() { InitializeCookieService(nullptr, nullptr); }
 
   ~CookieManagerTest() override {}
 
@@ -241,15 +240,13 @@
  protected:
   void InitializeCookieService(
       scoped_refptr<net::CookieMonster::PersistentCookieStore> store,
-      scoped_refptr<SessionCleanupCookieStore> cleanup_store,
-      scoped_refptr<SessionCleanupChannelIDStore> channel_id_store) {
+      scoped_refptr<SessionCleanupCookieStore> cleanup_store) {
     connection_error_seen_ = false;
     cookie_monster_ = std::make_unique<net::CookieMonster>(
         std::move(store), nullptr /*channel_id_service */,
         nullptr /* netlog */);
     cookie_service_ = std::make_unique<CookieManager>(
-        cookie_monster_.get(), std::move(cleanup_store),
-        std::move(channel_id_store), nullptr);
+        cookie_monster_.get(), std::move(cleanup_store), nullptr);
     cookie_service_->AddRequest(mojo::MakeRequest(&cookie_service_ptr_));
     service_wrapper_ =
         std::make_unique<SynchronousCookieManager>(cookie_service_ptr_.get());
@@ -1886,7 +1883,7 @@
  public:
   FlushableCookieManagerTest()
       : store_(base::MakeRefCounted<net::FlushablePersistentStore>()) {
-    InitializeCookieService(store_, nullptr, nullptr);
+    InitializeCookieService(store_, nullptr);
   }
 
   ~FlushableCookieManagerTest() override {}
@@ -1986,7 +1983,7 @@
   void SetUp() override {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     auto store = CreateCookieStore();
-    InitializeCookieService(store, store, nullptr);
+    InitializeCookieService(store, store);
   }
 
   scoped_refptr<SessionCleanupCookieStore> CreateCookieStore() {
@@ -2021,7 +2018,7 @@
 
   // Re-create the cookie store to make sure cookies are persisted.
   auto store = CreateCookieStore();
-  InitializeCookieService(store, store, nullptr);
+  InitializeCookieService(store, store);
 
   EXPECT_EQ(1u, service_wrapper()->GetAllCookies().size());
 }
@@ -2036,7 +2033,7 @@
   base::RunLoop().RunUntilIdle();
 
   auto store = CreateCookieStore();
-  InitializeCookieService(store, store, nullptr);
+  InitializeCookieService(store, store);
 
   EXPECT_EQ(0u, service_wrapper()->GetAllCookies().size());
 }
@@ -2051,7 +2048,7 @@
   base::RunLoop().RunUntilIdle();
 
   auto store = CreateCookieStore();
-  InitializeCookieService(store, store, nullptr);
+  InitializeCookieService(store, store);
 
   EXPECT_EQ(1u, service_wrapper()->GetAllCookies().size());
 }
@@ -2069,7 +2066,7 @@
   base::RunLoop().RunUntilIdle();
 
   auto store = CreateCookieStore();
-  InitializeCookieService(store, store, nullptr);
+  InitializeCookieService(store, store);
 
   EXPECT_EQ(1u, service_wrapper()->GetAllCookies().size());
 }
@@ -2085,7 +2082,7 @@
   base::RunLoop().RunUntilIdle();
 
   auto store = CreateCookieStore();
-  InitializeCookieService(store, store, nullptr);
+  InitializeCookieService(store, store);
 
   EXPECT_EQ(1u, service_wrapper()->GetAllCookies().size());
 }
@@ -2103,114 +2100,10 @@
   base::RunLoop().RunUntilIdle();
 
   auto store = CreateCookieStore();
-  InitializeCookieService(store, store, nullptr);
+  InitializeCookieService(store, store);
 
   EXPECT_EQ(1u, service_wrapper()->GetAllCookies().size());
 }
 
-// A test class having a channel ID store with persistent backing. The channel
-// ID store can be destroyed and recreated by calling InitializeCookieService
-// again.
-class SessionCleanupChannelIDCookieManagerTest : public CookieManagerTest {
- protected:
-  using ChannelIDVector =
-      std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>;
-
-  ~SessionCleanupChannelIDCookieManagerTest() override {}
-
-  void SetUp() override {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    store_ = CreateChannelIDStore();
-    ASSERT_EQ(0u, Load().size());
-    InitializeCookieService(nullptr, nullptr, store_);
-  }
-
-  void TearDown() override {
-    NukeService();
-    store_ = nullptr;
-    base::RunLoop().RunUntilIdle();
-  }
-
-  scoped_refptr<SessionCleanupChannelIDStore> CreateChannelIDStore() {
-    return base::MakeRefCounted<SessionCleanupChannelIDStore>(
-        temp_dir_.GetPath().Append(kTestCookiesFilename),
-        scoped_task_environment_.GetMainThreadTaskRunner());
-  }
-
-  ChannelIDVector Load() {
-    ChannelIDVector channel_ids;
-    base::RunLoop run_loop;
-    store_->Load(
-        base::BindRepeating(&SessionCleanupChannelIDCookieManagerTest::OnLoaded,
-                            base::Unretained(this), &run_loop, &channel_ids));
-    run_loop.Run();
-    return channel_ids;
-  }
-
-  void OnLoaded(base::RunLoop* run_loop,
-                ChannelIDVector* channel_ids_out,
-                std::unique_ptr<ChannelIDVector> channel_ids) {
-    channel_ids_out->swap(*channel_ids);
-    run_loop->Quit();
-  }
-
-  scoped_refptr<SessionCleanupChannelIDStore> store_;
-  base::ScopedTempDir temp_dir_;
-};
-
-TEST_F(SessionCleanupChannelIDCookieManagerTest, PersistSessionChannelIDs) {
-  store_->AddChannelID(net::ChannelIDStore::ChannelID(
-      kCookieDomain, base::Time::Now(), crypto::ECPrivateKey::Create()));
-
-  // Re-create the channel ID store to make sure channel IDs are persisted.
-  store_ = CreateChannelIDStore();
-  InitializeCookieService(nullptr, nullptr, store_);
-
-  EXPECT_EQ(1u, Load().size());
-}
-
-TEST_F(SessionCleanupChannelIDCookieManagerTest, DeleteSessionChannelIDs) {
-  store_->AddChannelID(net::ChannelIDStore::ChannelID(
-      kCookieDomain, base::Time::Now(), crypto::ECPrivateKey::Create()));
-
-  cookie_service_client()->SetContentSettings(
-      {CreateSetting(CONTENT_SETTING_SESSION_ONLY, kCookieURL)});
-  base::RunLoop().RunUntilIdle();
-
-  store_ = CreateChannelIDStore();
-  InitializeCookieService(nullptr, nullptr, store_);
-
-  EXPECT_EQ(0u, Load().size());
-}
-
-TEST_F(SessionCleanupChannelIDCookieManagerTest, SettingMustMatchDomain) {
-  store_->AddChannelID(net::ChannelIDStore::ChannelID(
-      kCookieDomain, base::Time::Now(), crypto::ECPrivateKey::Create()));
-
-  cookie_service_client()->SetContentSettings(
-      {CreateSetting(CONTENT_SETTING_SESSION_ONLY, "http://other.com")});
-  base::RunLoop().RunUntilIdle();
-
-  store_ = CreateChannelIDStore();
-  InitializeCookieService(nullptr, nullptr, store_);
-
-  EXPECT_EQ(1u, Load().size());
-}
-
-TEST_F(SessionCleanupChannelIDCookieManagerTest, ForceKeepSessionState) {
-  store_->AddChannelID(net::ChannelIDStore::ChannelID(
-      kCookieDomain, base::Time::Now(), crypto::ECPrivateKey::Create()));
-
-  cookie_service_client()->SetContentSettings(
-      {CreateSetting(CONTENT_SETTING_SESSION_ONLY, kCookieURL)});
-  cookie_service_client()->SetForceKeepSessionState();
-  base::RunLoop().RunUntilIdle();
-
-  store_ = CreateChannelIDStore();
-  InitializeCookieService(nullptr, nullptr, store_);
-
-  EXPECT_EQ(1u, Load().size());
-}
-
 }  // namespace
 }  // namespace network
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 6839958..d90c044 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -81,7 +81,6 @@
 #include "services/network/resolve_host_request.h"
 #include "services/network/resource_scheduler_client.h"
 #include "services/network/restricted_cookie_manager.h"
-#include "services/network/session_cleanup_channel_id_store.h"
 #include "services/network/session_cleanup_cookie_store.h"
 #include "services/network/ssl_config_service_mojo.h"
 #include "services/network/throttling/network_conditions.h"
@@ -594,7 +593,6 @@
       cookie_manager_(
           std::make_unique<CookieManager>(url_request_context->cookie_store(),
                                           nullptr,
-                                          nullptr,
                                           nullptr)),
       socket_factory_(
           std::make_unique<SocketFactory>(url_request_context_->net_log(),
@@ -1734,7 +1732,6 @@
   }
 
   scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store;
-  scoped_refptr<SessionCleanupChannelIDStore> session_cleanup_channel_id_store;
   if (params_->cookie_path) {
     scoped_refptr<base::SequencedTaskRunner> client_task_runner =
         base::MessageLoopCurrent::Get()->task_runner();
@@ -2078,7 +2075,6 @@
   cookie_manager_ = std::make_unique<CookieManager>(
       result.url_request_context->cookie_store(),
       std::move(session_cleanup_cookie_store),
-      std::move(session_cleanup_channel_id_store),
       std::move(params_->cookie_manager_params));
 
   return result;
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index 11acf0ebe..1c9d3708 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -30,6 +30,8 @@
     "cross_thread_shared_url_loader_factory_info.h",
     "features.cc",
     "features.h",
+    "is_potentially_trustworthy.cc",
+    "is_potentially_trustworthy.h",
     "net_adapters.cc",
     "net_adapters.h",
     "network_connection_tracker.cc",
@@ -74,6 +76,7 @@
     ":cpp_base",
     "//net",
     "//services/network/public/mojom",
+    "//url",
     "//url/ipc:url_ipc",
   ]
 
@@ -185,6 +188,7 @@
     "digitally_signed_mojom_traits_unittest.cc",
     "host_resolver_mojom_traits_unittest.cc",
     "ip_address_mojom_traits_unittest.cc",
+    "is_potentially_trustworthy_unittest.cc",
     "mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc",
     "mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc",
     "network_connection_tracker_unittest.cc",
diff --git a/services/network/public/cpp/is_potentially_trustworthy.cc b/services/network/public/cpp/is_potentially_trustworthy.cc
new file mode 100644
index 0000000..30dc499
--- /dev/null
+++ b/services/network/public/cpp/is_potentially_trustworthy.cc
@@ -0,0 +1,249 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "base/strings/pattern.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "url/origin.h"
+#include "url/scheme_host_port.h"
+#include "url/url_canon.h"
+#include "url/url_canon_ip.h"
+#include "url/url_canon_stdstring.h"
+#include "url/url_constants.h"
+#include "url/url_util.h"
+
+namespace network {
+
+namespace {
+
+#if DCHECK_IS_ON()
+base::Optional<base::SequenceChecker>& GetSequenceCheckerForAllowlist() {
+  static base::NoDestructor<base::Optional<base::SequenceChecker>> s_checker;
+  return *s_checker;
+}
+#endif
+
+#if DCHECK_IS_ON()
+#define DCHECK_ALLOWLIST_USED_ON_VALID_SEQUENCE()                            \
+  do {                                                                       \
+    if (GetSequenceCheckerForAllowlist().has_value()) {                      \
+      DCHECK(                                                                \
+          GetSequenceCheckerForAllowlist().value().CalledOnValidSequence()); \
+    }                                                                        \
+  } while (false);
+#else  // DCHECK_IS_ON()
+#define DCHECK_ALLOWLIST_USED_ON_VALID_SEQUENCE() EAT_STREAM_PARAMETERS
+#endif
+
+// |g_should_reparse_secure_origin_allowlist_cmdline| is needed to allow tests
+// to trigger reparsing of the cmdline switch.  This global should remain set to
+// |false| in production code.  See also thread safety notes in
+// GetSecureOriginAllowlist().
+bool g_should_reparse_secure_origin_allowlist_cmdline = false;
+
+// Given a hostname pattern with a wildcard such as "*.foo.com", returns
+// true if |hostname_pattern| meets both of these conditions:
+// 1.) A string matching |hostname_pattern| is a valid hostname.
+// 2.) Wildcards only appear beyond the eTLD+1. "*.foo.com" is considered
+//     valid but "*.com" is not.
+bool IsValidWildcardPattern(const std::string& hostname_pattern) {
+  // Replace wildcards with dummy values to check whether a matching origin is
+  // valid.
+  std::string wildcards_replaced;
+  if (!base::ReplaceChars(hostname_pattern, "*", "a", &wildcards_replaced))
+    return false;
+  // Construct a SchemeHostPort with a dummy scheme and port to check that the
+  // hostname is valid.
+  url::SchemeHostPort scheme_host_port(
+      GURL(base::StringPrintf("http://%s:80", wildcards_replaced.c_str())));
+  if (scheme_host_port.IsInvalid())
+    return false;
+
+  // Check that wildcards only appear beyond the eTLD+1.
+  size_t registry_length =
+      net::registry_controlled_domains::PermissiveGetHostRegistryLength(
+          hostname_pattern,
+          net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+  // std::string::npos should only be returned for empty inputs, which should be
+  // filtered out by the IsInvalid() check above.
+  CHECK(registry_length != std::string::npos);
+  // If there is no registrar portion, the pattern is considered invalid.
+  if (registry_length == 0)
+    return false;
+  // If there is no component before the registrar portion, or if the component
+  // immediately preceding the registrar portion contains a wildcard, the
+  // pattern is not considered valid.
+  std::string host_before_registrar =
+      hostname_pattern.substr(0, hostname_pattern.size() - registry_length);
+  std::vector<std::string> components =
+      base::SplitString(host_before_registrar, ".", base::KEEP_WHITESPACE,
+                        base::SPLIT_WANT_NONEMPTY);
+  if (components.size() == 0)
+    return false;
+  if (components.back().find("*") != std::string::npos)
+    return false;
+  return true;
+}
+
+// Canonicalizes each component of |hostname_pattern|, making no changes to
+// wildcard components or components that fail canonicalization. For example,
+// given a |hostname_pattern| of "TeSt.*.%46oo.com", the output will be
+// "test.*.foo.com".
+std::string CanonicalizePatternComponents(const std::string& hostname_pattern) {
+  std::string canonical_host;  // Do not modify outside of canon_output.
+  canonical_host.reserve(hostname_pattern.length());
+  url::StdStringCanonOutput canon_output(&canonical_host);
+
+  for (size_t current = 0; current < hostname_pattern.length(); current++) {
+    size_t begin = current;
+
+    // Advance to next "." or end.
+    current = hostname_pattern.find('.', begin);
+    if (current == std::string::npos)
+      current = hostname_pattern.length();
+
+    // Try to append the canonicalized version of this component.
+    int current_len = base::checked_cast<int>(current - begin);
+    if (hostname_pattern.substr(begin, current_len) == "*" ||
+        !url::CanonicalizeHostSubstring(
+            hostname_pattern.data(),
+            url::Component(base::checked_cast<int>(begin), current_len),
+            &canon_output)) {
+      // Failed to canonicalize this component; append as-is.
+      canon_output.Append(hostname_pattern.substr(begin, current_len).data(),
+                          current_len);
+    }
+
+    if (current < hostname_pattern.length())
+      canon_output.push_back('.');
+  }
+  canon_output.Complete();
+  return canonical_host;
+}
+
+std::vector<std::string> ParseSecureOriginAllowlistFromCmdline() {
+  // If kUnsafelyTreatInsecureOriginAsSecure option is given, then treat the
+  // value as a comma-separated list of origins or origin patterns. Callers
+  // that need to also check the kUnsafelyTreatInsecureOriginAsSecure pref
+  // value must instead use ParseAllowlist directly (as there is no way for
+  // CreateAllowlist() to access prefs). For renderer processes the pref and
+  // the switch will match, but for non-renderer processes the switch may
+  // not be set.
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  std::string origins_str = "";
+  if (command_line.HasSwitch(switches::kUnsafelyTreatInsecureOriginAsSecure)) {
+    origins_str = command_line.GetSwitchValueASCII(
+        switches::kUnsafelyTreatInsecureOriginAsSecure);
+  }
+  return ParseSecureOriginAllowlist(origins_str);
+}
+
+}  // namespace
+
+const std::vector<std::string>& GetSecureOriginAllowlist() {
+  // This function will initialize |s_allowlist| in a thread-safe way because of
+  // the way how |static| works - invoking base::NoDestructor's constructor and
+  // ParseSecureOriginAllowlistFromCmdline in a thread-safe way and only once.
+  //
+  // OTOH, if ResetSecureOriginAllowlistForTesting forces reinitialization, then
+  // things are not thread-safe anymore.  The DCHECK_ALLOWLIST_... below is
+  // trying to making sure that tests behave correctly.
+  DCHECK_ALLOWLIST_USED_ON_VALID_SEQUENCE();
+  static base::NoDestructor<std::vector<std::string>> s_allowlist(
+      ParseSecureOriginAllowlistFromCmdline());
+
+  // If unit tests set |g_should_reparse_secure_origin_allowlist_cmdline| then
+  // reading |g_should_reparse_secure_origin_allowlist_cmdline| as well as
+  // reinitializing |s_allowlist| are NOT THREAD SAFE.  This seems okay for unit
+  // tests (+ correct usage is verified by DCHECK_ALLOWLIST... above).
+  if (g_should_reparse_secure_origin_allowlist_cmdline) {
+    g_should_reparse_secure_origin_allowlist_cmdline = false;
+    *s_allowlist = ParseSecureOriginAllowlistFromCmdline();
+  }
+
+  return *s_allowlist;
+}
+
+void ResetSecureOriginAllowlistForTesting() {
+#if DCHECK_IS_ON()
+  DCHECK_ALLOWLIST_USED_ON_VALID_SEQUENCE();
+  // Enforce sequence-affinity only *after* the first call to
+  // ResetSecureOriginAllowlistForTesting.
+  if (!GetSequenceCheckerForAllowlist().has_value()) {
+    // Construct a new base::SequenceChecked emplacing it into base::Optional.
+    GetSequenceCheckerForAllowlist().emplace();
+  }
+#endif
+
+  g_should_reparse_secure_origin_allowlist_cmdline = true;
+}
+
+bool IsAllowlistedAsSecureOrigin(const url::Origin& origin,
+                                 const std::vector<std::string>& allowlist) {
+  if (base::ContainsValue(allowlist, origin.Serialize()))
+    return true;
+
+  for (const std::string& origin_or_pattern : allowlist) {
+    if (base::MatchPattern(origin.host(), origin_or_pattern))
+      return true;
+  }
+
+  return false;
+}
+
+std::vector<std::string> ParseSecureOriginAllowlist(
+    const std::string& origins_str) {
+  std::vector<std::string> origin_patterns;
+  for (const std::string& origin_str : base::SplitString(
+           origins_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
+    if (origin_str.find("*") != std::string::npos) {
+      if (IsValidWildcardPattern(origin_str)) {
+        std::string canonicalized_pattern =
+            CanonicalizePatternComponents(origin_str);
+        if (!canonicalized_pattern.empty()) {
+          origin_patterns.push_back(canonicalized_pattern);
+          continue;
+        }
+      }
+      LOG(ERROR) << "Allowlisted secure origin pattern " << origin_str
+                 << " is not valid; ignoring.";
+      continue;
+    }
+
+    // Drop .unique() origins, as they are unequal to any other origins.
+    url::Origin origin(url::Origin::Create(GURL(origin_str)));
+    if (!origin.opaque())
+      origin_patterns.push_back(origin.Serialize());
+  }
+
+  UMA_HISTOGRAM_COUNTS_100("Security.TreatInsecureOriginAsSecure",
+                           origin_patterns.size());
+
+#if defined(OS_CHROMEOS)
+  // For Crostini, we allow access to the default VM/container as a secure
+  // origin via the hostname penguin.linux.test. We are required to use a
+  // wildcard for the prefix because we do not know what the port number is.
+  // https://chromium.googlesource.com/chromiumos/docs/+/master/containers_and_vms.md
+  origin_patterns.push_back("*.linux.test");
+#endif
+
+  return origin_patterns;
+}
+
+}  // namespace network
diff --git a/services/network/public/cpp/is_potentially_trustworthy.h b/services/network/public/cpp/is_potentially_trustworthy.h
new file mode 100644
index 0000000..279f6c4
--- /dev/null
+++ b/services/network/public/cpp/is_potentially_trustworthy.h
@@ -0,0 +1,65 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_IS_POTENTIALLY_TRUSTWORTHY_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_IS_POTENTIALLY_TRUSTWORTHY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/component_export.h"
+#include "url/gurl.h"
+
+namespace url {
+class Origin;
+}  // namespace url
+
+namespace network {
+
+// Return an allowlist of origins and hostname patterns that need to be
+// considered trustworthy.  The allowlist is given by the
+// --unsafely-treat-insecure-origin-as-secure command-line option. See
+// https://www.w3.org/TR/powerful-features/#is-origin-trustworthy.
+//
+// The allowlist can contain origins and wildcard hostname patterns up to
+// eTLD+1. For example, the list may contain "http://foo.com",
+// "http://foo.com:8000", "*.foo.com", "*.foo.*.bar.com", and
+// "http://*.foo.bar.com", but not "*.co.uk", "*.com", or "test.*.com". Hostname
+// patterns must contain a wildcard somewhere (so "test.com" is not a valid
+// pattern) and wildcards can only replace full components ("test*.foo.com" is
+// not valid).
+//
+// Plain origins ("http://foo.com") are canonicalized when they are inserted
+// into this list by converting to url::Origin and serializing. For hostname
+// patterns, each component is individually canonicalized.
+//
+// This function is safe to be called from any thread in production code (tests
+// should see the warning in the ResetSecureOriginAllowlistForTesting comments
+// below).
+COMPONENT_EXPORT(NETWORK_CPP)
+const std::vector<std::string>& GetSecureOriginAllowlist();
+
+// Empties the secure origin allowlist.
+//
+// Thread-safety warning: Caller needs to ensure that all calls to
+// GetSecureOriginAllowlist, IsAllowlistedAsSecureOrigin and
+// ResetSecureOriginAllowlistForTesting are done from the same thread.
+COMPONENT_EXPORT(NETWORK_CPP) void ResetSecureOriginAllowlistForTesting();
+
+// Returns true if |origin| has a match in |allowlist|.  |allowlist| is usually
+// retrieved by GetSecureOriginAllowlist above.
+COMPONENT_EXPORT(NETWORK_CPP)
+bool IsAllowlistedAsSecureOrigin(const url::Origin& origin,
+                                 const std::vector<std::string>& allowlist);
+
+// Parses a comma-separated list of origins and wildcard hostname patterns.
+// This separate function allows callers other than GetSecureOriginAllowlist()
+// to explicitly pass an allowlist to be parsed.
+COMPONENT_EXPORT(NETWORK_CPP)
+std::vector<std::string> ParseSecureOriginAllowlist(
+    const std::string& origins_str);
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_PUBLIC_CPP_IS_POTENTIALLY_TRUSTWORTHY_H_
diff --git a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
new file mode 100644
index 0000000..ec7ced4
--- /dev/null
+++ b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -0,0 +1,112 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+
+#include "base/test/scoped_command_line.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace network {
+
+bool IsAllowlistedAsSecureOrigin(const url::Origin& origin) {
+  return IsAllowlistedAsSecureOrigin(origin,
+                                     network::GetSecureOriginAllowlist());
+}
+
+class SecureOriginAllowlistTest : public testing::Test {
+  void TearDown() override {
+    // Ensure that we reset the allowlisted origins without any flags applied.
+    ResetSecureOriginAllowlistForTesting();
+  }
+};
+
+TEST_F(SecureOriginAllowlistTest, UnsafelyTreatInsecureOriginAsSecure) {
+  EXPECT_FALSE(IsAllowlistedAsSecureOrigin(
+      url::Origin::Create(GURL("http://example.com/a.html"))));
+  EXPECT_FALSE(IsAllowlistedAsSecureOrigin(
+      url::Origin::Create(GURL("http://127.example.com/a.html"))));
+  // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy
+  // function (temporarily still in the //content layer)
+  // EXPECT_FALSE(IsPotentiallyTrustworthy("http://example.com/a.html"));
+  // EXPECT_FALSE(IsPotentiallyTrustworthy("http://127.example.com/a.html"));
+
+  // Add http://example.com and http://127.example.com to allowlist by
+  // command-line and see if they are now considered secure origins.
+  // (The command line is applied via
+  // ChromeContentClient::AddSecureSchemesAndOrigins)
+  base::test::ScopedCommandLine scoped_command_line;
+  base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
+  command_line->AppendSwitchASCII(
+      switches::kUnsafelyTreatInsecureOriginAsSecure,
+      "http://example.com,http://127.example.com");
+  ResetSecureOriginAllowlistForTesting();
+
+  // They should be now allow-listed.
+  EXPECT_TRUE(IsAllowlistedAsSecureOrigin(
+      url::Origin::Create(GURL("http://example.com/a.html"))));
+  EXPECT_TRUE(IsAllowlistedAsSecureOrigin(
+      url::Origin::Create(GURL("http://127.example.com/a.html"))));
+  // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy
+  // function (temporarily still in the //content layer)
+  // EXPECT_TRUE(IsPotentiallyTrustworthy("http://example.com/a.html"));
+  // EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.example.com/a.html"));
+
+  // Check that similarly named sites are not considered secure.
+  // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy
+  // function (temporarily still in the //content layer)
+  // EXPECT_FALSE(IsPotentiallyTrustworthy("http://128.example.com/a.html"));
+  // EXPECT_FALSE(
+  //    IsPotentiallyTrustworthy("http://foobar.127.example.com/a.html"));
+}
+
+TEST_F(SecureOriginAllowlistTest, HostnamePatterns) {
+  const struct HostnamePatternCase {
+    const char* pattern;
+    const char* test_input;
+    bool expected_secure;
+  } kTestCases[] = {
+      {"*.foo.com", "http://bar.foo.com", true},
+      {"*.foo.*.bar.com", "http://a.foo.b.bar.com:8000", true},
+      // For parsing/canonicalization simplicity, wildcard patterns can be
+      // hostnames only, not full origins.
+      {"http://*.foo.com", "http://bar.foo.com", false},
+      {"*://foo.com", "http://foo.com", false},
+      // Wildcards must be beyond eTLD+1.
+      {"*.co.uk", "http://foo.co.uk", false},
+      {"*.co.uk", "http://co.uk", false},
+      {"*.baz", "http://foo.baz", false},
+      {"foo.*.com", "http://foo.bar.com", false},
+      {"*.foo.baz", "http://a.foo.baz", true},
+      // Hostname patterns should be canonicalized.
+      {"*.FoO.com", "http://a.foo.com", true},
+      {"%2A.foo.com", "http://a.foo.com", false},
+      // Hostname patterns must contain a wildcard and a wildcard can only
+      // replace a component, not a part of a component.
+      {"foo.com", "http://foo.com", false},
+      {"test*.foo.com", "http://testblah.foo.com", false},
+      {"*foo.com", "http://testfoo.com", false},
+      {"foo*.com", "http://footest.com", false},
+  };
+
+  for (const auto& test : kTestCases) {
+    base::test::ScopedCommandLine scoped_command_line;
+    base::CommandLine* command_line =
+        scoped_command_line.GetProcessCommandLine();
+    command_line->AppendSwitchASCII(
+        switches::kUnsafelyTreatInsecureOriginAsSecure, test.pattern);
+    ResetSecureOriginAllowlistForTesting();
+    GURL input_url(test.test_input);
+    url::Origin input_origin = url::Origin::Create(input_url);
+    EXPECT_EQ(test.expected_secure, IsAllowlistedAsSecureOrigin(input_origin));
+    // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy
+    // function (temporarily still in the //content layer)
+    // EXPECT_EQ(test.expected_secure,
+    // IsPotentiallyTrustworthy(test.test_input));
+  }
+}
+
+}  // namespace network
diff --git a/services/network/public/cpp/net_ipc_param_traits.h b/services/network/public/cpp/net_ipc_param_traits.h
index 3cff701..8db5f62c 100644
--- a/services/network/public/cpp/net_ipc_param_traits.h
+++ b/services/network/public/cpp/net_ipc_param_traits.h
@@ -278,7 +278,6 @@
   IPC_STRUCT_TRAITS_MEMBER(new_top_frame_origin)
   IPC_STRUCT_TRAITS_MEMBER(new_referrer)
   IPC_STRUCT_TRAITS_MEMBER(insecure_scheme_was_upgraded)
-  IPC_STRUCT_TRAITS_MEMBER(is_signed_exchange_fallback_redirect)
   IPC_STRUCT_TRAITS_MEMBER(new_referrer_policy)
 IPC_STRUCT_TRAITS_END()
 
diff --git a/services/network/public/cpp/network_switches.cc b/services/network/public/cpp/network_switches.cc
index 60859bc4..7505008b 100644
--- a/services/network/public/cpp/network_switches.cc
+++ b/services/network/public/cpp/network_switches.cc
@@ -53,6 +53,16 @@
 // list of port numbers.
 const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports";
 
+// Treat given (insecure) origins as secure origins. Multiple origins can be
+// supplied as a comma-separated list. For the definition of secure contexts,
+// see https://w3c.github.io/webappsec-secure-contexts/ and
+// https://www.w3.org/TR/powerful-features/#is-origin-trustworthy
+//
+// Example:
+// --unsafely-treat-insecure-origin-as-secure=http://a.test,http://b.test
+const char kUnsafelyTreatInsecureOriginAsSecure[] =
+    "unsafely-treat-insecure-origin-as-secure";
+
 }  // namespace switches
 
 }  // namespace network
diff --git a/services/network/public/cpp/network_switches.h b/services/network/public/cpp/network_switches.h
index db64e5a..42de65482 100644
--- a/services/network/public/cpp/network_switches.h
+++ b/services/network/public/cpp/network_switches.h
@@ -21,6 +21,8 @@
 COMPONENT_EXPORT(NETWORK_CPP) extern const char kSSLKeyLogFile[];
 COMPONENT_EXPORT(NETWORK_CPP) extern const char kNoReferrers[];
 COMPONENT_EXPORT(NETWORK_CPP) extern const char kExplicitlyAllowedPorts[];
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const char kUnsafelyTreatInsecureOriginAsSecure[];
 
 }  // namespace switches
 
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index 1d46b702..049da805 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -340,8 +340,8 @@
   // For kRawFile
   mojo_base.mojom.File? file;
   // For kBlob
-  // TODO(richard.li): Deprecate this once NetworkService is fully shipped.
-  string? blob_uuid;
+  // TODO(Richard): Deprecate this once NetworkService is fully shipped.
+  string blob_uuid;
   // For kDataPipe
   network.mojom.DataPipeGetter? data_pipe_getter;
   // For kChunkedDataPipe
diff --git a/services/network/session_cleanup_channel_id_store.cc b/services/network/session_cleanup_channel_id_store.cc
deleted file mode 100644
index e3de7d99..0000000
--- a/services/network/session_cleanup_channel_id_store.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/network/session_cleanup_channel_id_store.h"
-
-#include <list>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "net/cookies/cookie_util.h"
-#include "net/extras/sqlite/sqlite_channel_id_store.h"
-#include "url/gurl.h"
-
-namespace network {
-
-SessionCleanupChannelIDStore::SessionCleanupChannelIDStore(
-    const base::FilePath& path,
-    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner)
-    : persistent_store_(
-          new net::SQLiteChannelIDStore(path, background_task_runner)) {
-  DCHECK(background_task_runner.get());
-}
-
-SessionCleanupChannelIDStore::~SessionCleanupChannelIDStore() {}
-
-void SessionCleanupChannelIDStore::DeleteSessionChannelIDs(
-    DeleteChannelIDPredicate delete_channel_id_predicate) {
-  if (force_keep_session_state_ || !delete_channel_id_predicate)
-    return;
-
-  std::list<std::string> session_only_server_identifiers;
-  for (const std::string& server_identifier : server_identifiers_) {
-    GURL url(net::cookie_util::CookieOriginToURL(server_identifier, true));
-    if (delete_channel_id_predicate.Run(url))
-      session_only_server_identifiers.push_back(server_identifier);
-  }
-  persistent_store_->DeleteAllInList(session_only_server_identifiers);
-}
-
-void SessionCleanupChannelIDStore::Load(const LoadedCallback& loaded_callback) {
-  persistent_store_->Load(base::BindRepeating(
-      &SessionCleanupChannelIDStore::OnLoad, this, loaded_callback));
-}
-
-void SessionCleanupChannelIDStore::AddChannelID(
-    const net::DefaultChannelIDStore::ChannelID& channel_id) {
-  server_identifiers_.insert(channel_id.server_identifier());
-  persistent_store_->AddChannelID(channel_id);
-}
-
-void SessionCleanupChannelIDStore::DeleteChannelID(
-    const net::DefaultChannelIDStore::ChannelID& channel_id) {
-  server_identifiers_.erase(channel_id.server_identifier());
-  persistent_store_->DeleteChannelID(channel_id);
-}
-
-void SessionCleanupChannelIDStore::Flush() {
-  persistent_store_->Flush();
-}
-
-void SessionCleanupChannelIDStore::SetForceKeepSessionState() {
-  force_keep_session_state_ = true;
-}
-
-void SessionCleanupChannelIDStore::OnLoad(
-    const LoadedCallback& loaded_callback,
-    std::unique_ptr<ChannelIDVector> channel_ids) {
-  for (const auto& channel_id : *channel_ids)
-    server_identifiers_.insert(channel_id->server_identifier());
-  loaded_callback.Run(std::move(channel_ids));
-}
-
-}  // namespace network
diff --git a/services/network/session_cleanup_channel_id_store.h b/services/network/session_cleanup_channel_id_store.h
deleted file mode 100644
index e32a493..0000000
--- a/services/network/session_cleanup_channel_id_store.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_NETWORK_SESSION_CLEANUP_CHANNEL_ID_STORE_H_
-#define SERVICES_NETWORK_SESSION_CLEANUP_CHANNEL_ID_STORE_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/compiler_specific.h"
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "net/extras/sqlite/sqlite_channel_id_store.h"
-#include "net/ssl/default_channel_id_store.h"
-
-class GURL;
-
-namespace base {
-class FilePath;
-class SequencedTaskRunner;
-}  // namespace base
-
-namespace network {
-
-// Implements a PersistentStore that keeps an in-memory map of channel IDs, and
-// allows deletion of channel IDs using the DeleteChannelIDPredicate. This is
-// used to clear channel IDs with session-only policy at the end of a session.
-class COMPONENT_EXPORT(NETWORK_SERVICE) SessionCleanupChannelIDStore
-    : public net::DefaultChannelIDStore::PersistentStore {
- public:
-  // Returns true if the channel ID for the URL should be deleted.
-  using DeleteChannelIDPredicate = base::RepeatingCallback<bool(const GURL&)>;
-
-  // Create or open persistent store in file |path|. All I/O tasks are performed
-  // in background using |background_task_runner|.
-  SessionCleanupChannelIDStore(
-      const base::FilePath& path,
-      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
-
-  // net::DefaultChannelIDStore::PersistentStore:
-  void Load(const LoadedCallback& loaded_callback) override;
-  void AddChannelID(
-      const net::DefaultChannelIDStore::ChannelID& channel_id) override;
-  void DeleteChannelID(
-      const net::DefaultChannelIDStore::ChannelID& channel_id) override;
-  void Flush() override;
-  void SetForceKeepSessionState() override;
-
-  // Should be called at the end of a session. Deletes all channel IDs that
-  // |delete_channel_id_predicate| returns true for.
-  void DeleteSessionChannelIDs(
-      DeleteChannelIDPredicate delete_channel_id_predicate);
-
- protected:
-  ~SessionCleanupChannelIDStore() override;
-
- private:
-  using ChannelIDVector =
-      std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>;
-
-  void OnLoad(const LoadedCallback& loaded_callback,
-              std::unique_ptr<ChannelIDVector> channel_ids);
-
-  scoped_refptr<net::SQLiteChannelIDStore> persistent_store_;
-  // Cache of server identifiers we have channel IDs stored for.
-  std::set<std::string> server_identifiers_;
-  // When set to true, DeleteSessionChannelIDs will be a no-op, and all channel
-  // IDs will be kept.
-  bool force_keep_session_state_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(SessionCleanupChannelIDStore);
-};
-
-}  // namespace network
-
-#endif  // SERVICES_NETWORK_SESSION_CLEANUP_CHANNEL_ID_STORE_H_
diff --git a/services/network/session_cleanup_channel_id_store_unittest.cc b/services/network/session_cleanup_channel_id_store_unittest.cc
deleted file mode 100644
index 512be9f2..0000000
--- a/services/network/session_cleanup_channel_id_store_unittest.cc
+++ /dev/null
@@ -1,186 +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.
-
-#include "services/network/session_cleanup_channel_id_store.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "net/test/channel_id_test_util.h"
-#include "net/test/test_data_directory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace network {
-namespace {
-
-using ChannelIDVector =
-    std::vector<std::unique_ptr<net::DefaultChannelIDStore::ChannelID>>;
-
-const base::FilePath::CharType kTestChannelIDFilename[] =
-    FILE_PATH_LITERAL("ChannelID");
-
-class SessionCleanupChannelIDStoreTest : public testing::Test {
- public:
-  ChannelIDVector Load() {
-    ChannelIDVector channel_ids;
-    base::RunLoop run_loop;
-    store_->Load(
-        base::BindRepeating(&SessionCleanupChannelIDStoreTest::OnLoaded,
-                            base::Unretained(this), &run_loop, &channel_ids));
-    run_loop.Run();
-    return channel_ids;
-  }
-
-  void OnLoaded(base::RunLoop* run_loop,
-                ChannelIDVector* channel_ids_out,
-                std::unique_ptr<ChannelIDVector> channel_ids) {
-    channel_ids_out->swap(*channel_ids);
-    run_loop->Quit();
-  }
-
-  ChannelIDVector CreateAndLoad() {
-    store_ = base::MakeRefCounted<SessionCleanupChannelIDStore>(
-        temp_dir_.GetPath().Append(kTestChannelIDFilename),
-        scoped_task_environment_.GetMainThreadTaskRunner());
-    return Load();
-  }
-
- protected:
-  void SetUp() override {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    ChannelIDVector channel_ids = CreateAndLoad();
-    ASSERT_EQ(0u, channel_ids.size());
-  }
-
-  void TearDown() override {
-    store_ = nullptr;
-    scoped_task_environment_.RunUntilIdle();
-  }
-
-  base::ScopedTempDir temp_dir_;
-  scoped_refptr<SessionCleanupChannelIDStore> store_;
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-};
-
-TEST_F(SessionCleanupChannelIDStoreTest, TestPersistence) {
-  std::unique_ptr<crypto::ECPrivateKey> goog_key(
-      crypto::ECPrivateKey::Create());
-  std::unique_ptr<crypto::ECPrivateKey> foo_key(crypto::ECPrivateKey::Create());
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "google.com", base::Time::FromDoubleT(1), goog_key->Copy()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "foo.com", base::Time::FromDoubleT(3), foo_key->Copy()));
-
-  // Replace the store effectively destroying the current one and forcing it
-  // to write its data to disk. Then we can see if after loading it again it
-  // is still there.
-  store_ = nullptr;
-  // Make sure we wait until the destructor has run.
-  scoped_task_environment_.RunUntilIdle();
-
-  // Reload and test for persistence
-  ChannelIDVector channel_ids = CreateAndLoad();
-  ASSERT_EQ(2u, channel_ids.size());
-  net::DefaultChannelIDStore::ChannelID* goog_channel_id;
-  net::DefaultChannelIDStore::ChannelID* foo_channel_id;
-  if (channel_ids[0]->server_identifier() == "google.com") {
-    goog_channel_id = channel_ids[0].get();
-    foo_channel_id = channel_ids[1].get();
-  } else {
-    goog_channel_id = channel_ids[1].get();
-    foo_channel_id = channel_ids[0].get();
-  }
-  EXPECT_EQ("google.com", goog_channel_id->server_identifier());
-  EXPECT_TRUE(net::KeysEqual(goog_key.get(), goog_channel_id->key()));
-  EXPECT_EQ(1, goog_channel_id->creation_time().ToDoubleT());
-  EXPECT_EQ("foo.com", foo_channel_id->server_identifier());
-  EXPECT_TRUE(net::KeysEqual(foo_key.get(), foo_channel_id->key()));
-  EXPECT_EQ(3, foo_channel_id->creation_time().ToDoubleT());
-
-  // Now delete the channel ID and check persistence again.
-  store_->DeleteChannelID(*channel_ids[0]);
-  store_->DeleteChannelID(*channel_ids[1]);
-  store_ = nullptr;
-  // Make sure we wait until the destructor has run.
-  scoped_task_environment_.RunUntilIdle();
-
-  // Reload and check if the channel ID has been removed.
-  channel_ids = CreateAndLoad();
-  EXPECT_EQ(0u, channel_ids.size());
-}
-
-TEST_F(SessionCleanupChannelIDStoreTest, TestDeleteSessionChannelIDs) {
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "google.com", base::Time::FromDoubleT(1),
-      crypto::ECPrivateKey::Create()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "nonpersistent.com", base::Time::FromDoubleT(3),
-      crypto::ECPrivateKey::Create()));
-
-  // Replace the store and force it to write to disk.
-  store_ = nullptr;
-  scoped_task_environment_.RunUntilIdle();
-  ChannelIDVector channel_ids = CreateAndLoad();
-  EXPECT_EQ(2u, channel_ids.size());
-
-  // Add another two channel IDs before closing the store. Because additions are
-  // delayed and committed to disk in batches, these will not be committed until
-  // the store is destroyed, which is after the policy is applied. The pending
-  // operation pruning logic should prevent the "nonpersistent.com" ID from
-  // being committed to disk.
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "nonpersistent.com", base::Time::FromDoubleT(5),
-      crypto::ECPrivateKey::Create()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "persistent.com", base::Time::FromDoubleT(7),
-      crypto::ECPrivateKey::Create()));
-
-  store_->DeleteSessionChannelIDs(base::BindRepeating(
-      [](const GURL& url) { return url.host() == "nonpersistent.com"; }));
-  scoped_task_environment_.RunUntilIdle();
-  // Now close the store, and the nonpersistent.com channel IDs should have been
-  // deleted.
-  store_ = nullptr;
-  scoped_task_environment_.RunUntilIdle();
-
-  // Reload and check that the nonpersistent.com channel IDs have been removed.
-  channel_ids = CreateAndLoad();
-  EXPECT_EQ(2u, channel_ids.size());
-  for (const auto& id : channel_ids) {
-    EXPECT_NE("nonpersistent.com", id->server_identifier());
-  }
-}
-
-TEST_F(SessionCleanupChannelIDStoreTest, TestForceKeepSessionState) {
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "google.com", base::Time::FromDoubleT(1),
-      crypto::ECPrivateKey::Create()));
-  store_->AddChannelID(net::DefaultChannelIDStore::ChannelID(
-      "nonpersistent.com", base::Time::FromDoubleT(3),
-      crypto::ECPrivateKey::Create()));
-
-  store_->SetForceKeepSessionState();
-  store_->DeleteSessionChannelIDs(base::BindRepeating(
-      [](const GURL& url) { return url.host() == "nonpersistent.com"; }));
-  scoped_task_environment_.RunUntilIdle();
-
-  store_ = nullptr;
-  scoped_task_environment_.RunUntilIdle();
-
-  // Reload and check that the all channel IDs are still present.
-  ChannelIDVector channel_ids = CreateAndLoad();
-  EXPECT_EQ(2u, channel_ids.size());
-}
-
-}  // namespace
-}  // namespace network
diff --git a/services/network/session_cleanup_cookie_store.cc b/services/network/session_cleanup_cookie_store.cc
index 74939b56..8cd780da 100644
--- a/services/network/session_cleanup_cookie_store.cc
+++ b/services/network/session_cleanup_cookie_store.cc
@@ -119,9 +119,9 @@
   force_keep_session_state_ = true;
 }
 
-void SessionCleanupCookieStore::SetBeforeFlushCallback(
+void SessionCleanupCookieStore::SetBeforeCommitCallback(
     base::RepeatingClosure callback) {
-  persistent_store_->SetBeforeFlushCallback(std::move(callback));
+  persistent_store_->SetBeforeCommitCallback(std::move(callback));
 }
 
 void SessionCleanupCookieStore::Flush(base::OnceClosure callback) {
diff --git a/services/network/session_cleanup_cookie_store.h b/services/network/session_cleanup_cookie_store.h
index 2443984..6cbdea17 100644
--- a/services/network/session_cleanup_cookie_store.h
+++ b/services/network/session_cleanup_cookie_store.h
@@ -52,7 +52,7 @@
   void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
   void DeleteCookie(const net::CanonicalCookie& cc) override;
   void SetForceKeepSessionState() override;
-  void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
+  void SetBeforeCommitCallback(base::RepeatingClosure callback) override;
   void Flush(base::OnceClosure callback) override;
 
   // Should be called at the end of a session. Deletes all cookies that
diff --git a/services/viz/public/cpp/compositing/shared_quad_state_struct_traits.h b/services/viz/public/cpp/compositing/shared_quad_state_struct_traits.h
index 247087f..fe9ba92 100644
--- a/services/viz/public/cpp/compositing/shared_quad_state_struct_traits.h
+++ b/services/viz/public/cpp/compositing/shared_quad_state_struct_traits.h
@@ -7,6 +7,7 @@
 
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "services/viz/public/interfaces/compositing/shared_quad_state.mojom-shared.h"
+#include "ui/gfx/mojo/rrect_f_struct_traits.h"
 
 namespace mojo {
 
@@ -34,6 +35,11 @@
     return input.sqs->visible_quad_layer_rect;
   }
 
+  static const gfx::RRectF& rounded_corner_bounds(
+      const OptSharedQuadState& input) {
+    return input.sqs->rounded_corner_bounds;
+  }
+
   static const gfx::Rect& clip_rect(const OptSharedQuadState& input) {
     return input.sqs->clip_rect;
   }
@@ -75,6 +81,11 @@
     return sqs.visible_quad_layer_rect;
   }
 
+  static const gfx::RRectF& rounded_corner_bounds(
+      const viz::SharedQuadState& sqs) {
+    return sqs.rounded_corner_bounds;
+  }
+
   static const gfx::Rect& clip_rect(const viz::SharedQuadState& sqs) {
     return sqs.clip_rect;
   }
@@ -102,6 +113,7 @@
     if (!data.ReadQuadToTargetTransform(&out->quad_to_target_transform) ||
         !data.ReadQuadLayerRect(&out->quad_layer_rect) ||
         !data.ReadVisibleQuadLayerRect(&out->visible_quad_layer_rect) ||
+        !data.ReadRoundedCornerBounds(&out->rounded_corner_bounds) ||
         !data.ReadClipRect(&out->clip_rect)) {
       return false;
     }
diff --git a/services/viz/public/cpp/compositing/struct_traits_perftest.cc b/services/viz/public/cpp/compositing/struct_traits_perftest.cc
index 421beb9..7207f7d 100644
--- a/services/viz/public/cpp/compositing/struct_traits_perftest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_perftest.cc
@@ -157,6 +157,8 @@
     gfx::RectF arbitrary_rectf1(4.2f, -922.1f, 15.6f, 29.5f);
     gfx::RRectF arbitrary_rrectf1(4.2f, -922.1f, 15.6f, 29.5f, 1.2f, 2.3f, 3.4f,
                                   4.5f, 5.6f, 6.7f, 7.8f, 8.9f);
+    gfx::RRectF arbitrary_rrectf2(gfx::RectF(1.f, 2.f, 30.f, 45.f), 5.f);
+    gfx::RRectF arbitrary_rrectf3(gfx::RectF(5.f, 6.f, 20.f, 35.f), 2.f, 3.f);
     gfx::PointF arbitrary_pointf1(31.4f, 15.9f);
     gfx::PointF arbitrary_pointf2(26.5f, -35.8f);
     float arbitrary_float1 = 0.7f;
@@ -209,9 +211,9 @@
       SharedQuadState* shared_state1_in =
           pass_in->CreateAndAppendSharedQuadState();
       shared_state1_in->SetAll(
-          arbitrary_matrix1, arbitrary_rect1, arbitrary_rect1, arbitrary_rect2,
-          arbitrary_bool1, arbitrary_bool1, arbitrary_float1,
-          arbitrary_blend_mode1, arbitrary_context_id1);
+          arbitrary_matrix1, arbitrary_rect1, arbitrary_rect1,
+          arbitrary_rrectf1, arbitrary_rect2, arbitrary_bool1, arbitrary_bool1,
+          arbitrary_float1, arbitrary_blend_mode1, arbitrary_context_id1);
 
       auto* texture_in = pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>();
       texture_in->SetAll(
@@ -251,9 +253,9 @@
       SharedQuadState* shared_state2_in =
           pass_in->CreateAndAppendSharedQuadState();
       shared_state2_in->SetAll(
-          arbitrary_matrix2, arbitrary_rect2, arbitrary_rect2, arbitrary_rect3,
-          arbitrary_bool1, arbitrary_bool1, arbitrary_float2,
-          arbitrary_blend_mode2, arbitrary_context_id2);
+          arbitrary_matrix2, arbitrary_rect2, arbitrary_rect2,
+          arbitrary_rrectf2, arbitrary_rect3, arbitrary_bool1, arbitrary_bool1,
+          arbitrary_float2, arbitrary_blend_mode2, arbitrary_context_id2);
       for (uint32_t j = 0; j < 6; ++j) {
         auto* tile_in = pass_in->CreateAndAppendDrawQuad<TileDrawQuad>();
         tile_in->SetAll(shared_state2_in, arbitrary_rect2,
@@ -269,9 +271,9 @@
       SharedQuadState* shared_state3_in =
           pass_in->CreateAndAppendSharedQuadState();
       shared_state3_in->SetAll(
-          arbitrary_matrix1, arbitrary_rect3, arbitrary_rect3, arbitrary_rect1,
-          arbitrary_bool1, arbitrary_bool1, arbitrary_float3,
-          arbitrary_blend_mode3, arbitrary_context_id3);
+          arbitrary_matrix1, arbitrary_rect3, arbitrary_rect3,
+          arbitrary_rrectf3, arbitrary_rect1, arbitrary_bool1, arbitrary_bool1,
+          arbitrary_float3, arbitrary_blend_mode3, arbitrary_context_id3);
       for (uint32_t j = 0; j < 5; ++j) {
         auto* solidcolor_in =
             pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
index d552e6ee..c8f50569 100644
--- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -413,6 +413,7 @@
                                                 13.f, 14.f, 15.f, 16.f);
   const gfx::Rect layer_rect(1234, 5678);
   const gfx::Rect visible_layer_rect(12, 34, 56, 78);
+  const gfx::RRectF rounded_corner_bounds(gfx::RectF(1.f, 2.f, 30.f, 40.f), 5);
   const gfx::Rect clip_rect(123, 456, 789, 101112);
   const bool is_clipped = true;
   bool are_contents_opaque = true;
@@ -421,14 +422,16 @@
   const int sorting_context_id = 1337;
   SharedQuadState input_sqs;
   input_sqs.SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
-                   clip_rect, is_clipped, are_contents_opaque, opacity,
-                   blend_mode, sorting_context_id);
+                   rounded_corner_bounds, clip_rect, is_clipped,
+                   are_contents_opaque, opacity, blend_mode,
+                   sorting_context_id);
   SharedQuadState output_sqs;
   mojo::test::SerializeAndDeserialize<mojom::SharedQuadState>(&input_sqs,
                                                               &output_sqs);
   EXPECT_EQ(quad_to_target_transform, output_sqs.quad_to_target_transform);
   EXPECT_EQ(layer_rect, output_sqs.quad_layer_rect);
   EXPECT_EQ(visible_layer_rect, output_sqs.visible_quad_layer_rect);
+  EXPECT_EQ(rounded_corner_bounds, output_sqs.rounded_corner_bounds);
   EXPECT_EQ(clip_rect, output_sqs.clip_rect);
   EXPECT_EQ(is_clipped, output_sqs.is_clipped);
   EXPECT_EQ(opacity, output_sqs.opacity);
@@ -449,6 +452,8 @@
       15.f, 16.f);
   const gfx::Rect sqs_layer_rect(1234, 5678);
   const gfx::Rect sqs_visible_layer_rect(12, 34, 56, 78);
+  const gfx::RRectF sqs_rounded_corner_bounds(gfx::RectF(3.f, 4.f, 50.f, 15.f),
+                                              3);
   const gfx::Rect sqs_clip_rect(123, 456, 789, 101112);
   const bool sqs_is_clipped = true;
   bool sqs_are_contents_opaque = false;
@@ -457,9 +462,9 @@
   const int sqs_sorting_context_id = 1337;
   SharedQuadState* sqs = render_pass->CreateAndAppendSharedQuadState();
   sqs->SetAll(sqs_quad_to_target_transform, sqs_layer_rect,
-              sqs_visible_layer_rect, sqs_clip_rect, sqs_is_clipped,
-              sqs_are_contents_opaque, sqs_opacity, sqs_blend_mode,
-              sqs_sorting_context_id);
+              sqs_visible_layer_rect, sqs_rounded_corner_bounds, sqs_clip_rect,
+              sqs_is_clipped, sqs_are_contents_opaque, sqs_opacity,
+              sqs_blend_mode, sqs_sorting_context_id);
 
   // DebugBorderDrawQuad.
   const gfx::Rect rect1(1234, 4321, 1357, 7531);
@@ -540,6 +545,7 @@
   EXPECT_EQ(sqs_quad_to_target_transform, out_sqs->quad_to_target_transform);
   EXPECT_EQ(sqs_layer_rect, out_sqs->quad_layer_rect);
   EXPECT_EQ(sqs_visible_layer_rect, out_sqs->visible_quad_layer_rect);
+  EXPECT_EQ(sqs_rounded_corner_bounds, out_sqs->rounded_corner_bounds);
   EXPECT_EQ(sqs_clip_rect, out_sqs->clip_rect);
   EXPECT_EQ(sqs_is_clipped, out_sqs->is_clipped);
   EXPECT_EQ(sqs_are_contents_opaque, out_sqs->are_contents_opaque);
@@ -762,6 +768,7 @@
       gfx::Transform(16.1f, 15.3f, 14.3f, 13.7f, 12.2f, 11.4f, 10.4f, 9.8f,
                      8.1f, 7.3f, 6.3f, 5.7f, 4.8f, 3.4f, 2.4f, 1.2f),
       gfx::Rect(1, 2), gfx::Rect(1337, 5679, 9101112, 131415),
+      gfx::RRectF(gfx::RectF(5.f, 6.f, 70.f, 89.f), 10.f),
       gfx::Rect(1357, 2468, 121314, 1337), true, true, 2, SkBlendMode::kSrcOver,
       1);
 
@@ -770,6 +777,7 @@
       gfx::Transform(1.1f, 2.3f, 3.3f, 4.7f, 5.2f, 6.4f, 7.4f, 8.8f, 9.1f,
                      10.3f, 11.3f, 12.7f, 13.8f, 14.4f, 15.4f, 16.2f),
       gfx::Rect(1337, 1234), gfx::Rect(1234, 5678, 9101112, 13141516),
+      gfx::RRectF(gfx::RectF(23.f, 45.f, 60.f, 70.f), 8.f),
       gfx::Rect(1357, 2468, 121314, 1337), true, true, 2, SkBlendMode::kSrcOver,
       1);
 
@@ -826,6 +834,8 @@
   EXPECT_EQ(shared_state_1->quad_layer_rect, out_sqs1->quad_layer_rect);
   EXPECT_EQ(shared_state_1->visible_quad_layer_rect,
             out_sqs1->visible_quad_layer_rect);
+  EXPECT_EQ(shared_state_1->rounded_corner_bounds,
+            out_sqs1->rounded_corner_bounds);
   EXPECT_EQ(shared_state_1->clip_rect, out_sqs1->clip_rect);
   EXPECT_EQ(shared_state_1->is_clipped, out_sqs1->is_clipped);
   EXPECT_EQ(shared_state_1->opacity, out_sqs1->opacity);
@@ -838,6 +848,8 @@
   EXPECT_EQ(shared_state_2->quad_layer_rect, out_sqs2->quad_layer_rect);
   EXPECT_EQ(shared_state_2->visible_quad_layer_rect,
             out_sqs2->visible_quad_layer_rect);
+  EXPECT_EQ(shared_state_2->rounded_corner_bounds,
+            out_sqs2->rounded_corner_bounds);
   EXPECT_EQ(shared_state_2->clip_rect, out_sqs2->clip_rect);
   EXPECT_EQ(shared_state_2->is_clipped, out_sqs2->is_clipped);
   EXPECT_EQ(shared_state_2->opacity, out_sqs2->opacity);
diff --git a/services/viz/public/interfaces/compositing/shared_quad_state.mojom b/services/viz/public/interfaces/compositing/shared_quad_state.mojom
index a6d8222..6ca90c7 100644
--- a/services/viz/public/interfaces/compositing/shared_quad_state.mojom
+++ b/services/viz/public/interfaces/compositing/shared_quad_state.mojom
@@ -5,6 +5,7 @@
 module viz.mojom;
 
 import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/mojo/rrect_f.mojom";
 import "ui/gfx/mojo/transform.mojom";
 
 struct SharedQuadState {
@@ -18,6 +19,10 @@
   // of the quad rects.
   gfx.mojom.Rect visible_quad_layer_rect;
 
+  // This rect lives in the target content space. It defines the corner radius
+  // to clip the quads with.
+  gfx.mojom.RRectF rounded_corner_bounds;
+
   // This rect lives in the target content space.
   gfx.mojom.Rect clip_rect;
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e93ca30..618714e 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3909,9 +3909,9 @@
             ],
             "experiments": [
                 {
-                    "name": "SlowPageTriggeringFor3G_20181204",
+                    "name": "SlowPageTriggeringFor4G_20190312",
                     "params": {
-                        "session_max_ect_trigger": "3G"
+                        "session_max_ect_trigger": "4G"
                     },
                     "enable_features": [
                         "PreviewsSlowPageTriggering"
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn
index 80f1162..6aad7aa 100644
--- a/third_party/android_deps/BUILD.gn
+++ b/third_party/android_deps/BUILD.gn
@@ -24,91 +24,7 @@
   ]
 }
 
-java_group("android_support_multidex_java") {
-  deps = [
-    ":com_android_support_multidex_java",
-  ]
-}
-java_group("android_support_annotations_java") {
-  deps = [
-    ":com_android_support_support_annotations_java",
-  ]
-}
-java_group("android_support_cardview_java") {
-  deps = [
-    ":com_android_support_cardview_v7_java",
-  ]
-}
-java_group("android_support_compat_java") {
-  deps = [
-    ":com_android_support_support_compat_java",
-  ]
-}
-java_group("android_support_core_ui_java") {
-  deps = [
-    ":com_android_support_support_core_ui_java",
-  ]
-}
-java_group("android_support_core_utils_java") {
-  deps = [
-    ":com_android_support_support_core_utils_java",
-  ]
-}
-java_group("android_support_design_java") {
-  deps = [
-    ":com_android_support_design_java",
-  ]
-}
-java_group("android_support_fragment_java") {
-  deps = [
-    ":com_android_support_support_fragment_java",
-  ]
-}
-java_group("android_support_media_compat_java") {
-  deps = [
-    ":com_android_support_support_media_compat_java",
-  ]
-}
-java_group("android_support_transition_java") {
-  deps = [
-    ":com_android_support_transition_java",
-  ]
-}
-java_group("android_support_v7_appcompat_java_internal") {
-  deps = [
-    ":com_android_support_appcompat_v7_java",
-  ]
-}
-java_group("android_support_v7_gridlayout_java") {
-  deps = [
-    ":com_android_support_gridlayout_v7_java",
-  ]
-}
-java_group("android_support_v7_mediarouter_java") {
-  deps = [
-    ":com_android_support_mediarouter_v7_java",
-  ]
-}
-java_group("android_support_v7_palette_java") {
-  deps = [
-    ":com_android_support_palette_v7_java",
-  ]
-}
-java_group("android_support_v7_recyclerview_java") {
-  deps = [
-    ":com_android_support_recyclerview_v7_java",
-  ]
-}
-java_group("android_support_v13_java") {
-  deps = [
-    ":com_android_support_support_v13_java",
-  ]
-}
-java_group("android_support_vector_drawable_java") {
-  deps = [
-    ":com_android_support_support_vector_drawable_java",
-  ]
-}
+# Aliases
 java_group("google_play_services_basement_java") {
   deps = [
     ":com_google_android_gms_play_services_basement_java",
@@ -185,8 +101,7 @@
   ]
 }
 
-# The dependencies below don't seem to be used but break downstream builds
-# when not defined.
+# The dependencies below are used by chromecast internal.
 java_group("android_support_v7_preference_java") {
   deps = [
     ":com_android_support_preference_v7_java",
diff --git a/third_party/android_media/BUILD.gn b/third_party/android_media/BUILD.gn
index 9e85c8ff..75a1082d 100644
--- a/third_party/android_media/BUILD.gn
+++ b/third_party/android_media/BUILD.gn
@@ -11,7 +11,7 @@
   resource_dirs = [ "java/res" ]
   deps = [
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_mediarouter_java",
+    "//third_party/android_deps:com_android_support_mediarouter_v7_java",
   ]
 }
 
@@ -21,6 +21,6 @@
   deps = [
     ":android_media_resources",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_mediarouter_java",
+    "//third_party/android_deps:com_android_support_mediarouter_v7_java",
   ]
 }
diff --git a/third_party/android_swipe_refresh/BUILD.gn b/third_party/android_swipe_refresh/BUILD.gn
index d9c19f28..dd07f426 100644
--- a/third_party/android_swipe_refresh/BUILD.gn
+++ b/third_party/android_swipe_refresh/BUILD.gn
@@ -14,6 +14,6 @@
     "java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java",
   ]
   deps = [
-    "//third_party/android_deps:android_support_core_ui_java",
+    "//third_party/android_deps:com_android_support_support_core_ui_java",
   ]
 }
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 0694a2a..37b6b0b 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -90,7 +90,7 @@
   android_library("blink_headers_java") {
     deps = [
       "//services/network/public/mojom:mojom_java",
-      "//third_party/android_deps:android_support_annotations_java",
+      "//third_party/android_deps:com_android_support_support_annotations_java",
     ]
     srcjar_deps = [ ":blink_headers_java_enums_srcjar" ]
   }
diff --git a/third_party/blink/public/mojom/background_sync/background_sync.mojom b/third_party/blink/public/mojom/background_sync/background_sync.mojom
index 8ec2bb4..a11fb0bcd 100644
--- a/third_party/blink/public/mojom/background_sync/background_sync.mojom
+++ b/third_party/blink/public/mojom/background_sync/background_sync.mojom
@@ -6,6 +6,10 @@
 
 struct SyncRegistrationOptions {
   string tag = "";
+  // Minimum interval guaranteed between two Periodic Background Sync events,
+  // in ms. This must be -1 for One-Shot Sync registrations, and must be >=0
+  // for Periodic Sync registrations.
+  int64 min_interval = -1;
 };
 
 enum BackgroundSyncError {
@@ -15,7 +19,7 @@
   NO_SERVICE_WORKER,
   NOT_ALLOWED,
   PERMISSION_DENIED,
-  MAX=PERMISSION_DENIED
+  MAX=PERMISSION_DENIED,
 };
 
 enum BackgroundSyncState {
@@ -26,13 +30,19 @@
 
 enum BackgroundSyncEventLastChance {
   IS_NOT_LAST_CHANCE,
-  IS_LAST_CHANCE
+  IS_LAST_CHANCE,
+};
+
+enum BackgroundSyncType {
+  ONE_SHOT,
+  PERIODIC,
 };
 
 interface BackgroundSyncService {
   Register(SyncRegistrationOptions options, int64 service_worker_registration_id)
       => (BackgroundSyncError err, SyncRegistrationOptions options);
-  DidResolveRegistration(int64 service_worker_registration_id, string tag);
+  DidResolveRegistration(int64 service_worker_registration_id, string tag,
+                         BackgroundSyncType sync_type);
   GetRegistrations(int64 service_worker_registration_id)
       => (BackgroundSyncError err, array<SyncRegistrationOptions> registrations);
 };
diff --git a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
index b6ace2f..622426f 100644
--- a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
+++ b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
@@ -272,28 +272,23 @@
 };
 
 struct IDBCursorValue {
-  IDBKey key;
-  IDBKey primary_key;
-  IDBValue value;
+  array<IDBKey> keys;
+  array<IDBKey> primary_keys;
+  array<IDBValue> values;
 };
 
+// Advance(), CursorContinue(), and Prefetch() can call its return callback in
+// one of 3 ways:
+// * with |error| set and |value| unset, if an error occurs
+// * with |error| unset and |value| set, under normal operation
+// * with |error| unset and |value| unset, under normal operation when the end
+//   of the source being iterated is reached
 interface IDBCursor {
-  // Advance() can call its return callback in one of 3 ways:
-  // * with |error| set and |value| unset, if an error occurs
-  // * with |error| unset and |value| set, under normal operation
-  // * with |error| unset and |value| unset, under normal operation when the end
-  //   of the source being iterated is reached
   Advance(uint32 count) => (IDBError? error, IDBCursorValue? value);
-
-  // CursorContinue() can call its return callback in one of 3 ways:
-  // * with |error| set and |value| unset, if an error occurs
-  // * with |error| unset and |value| set, under normal operation
-  // * with |error| unset and |value| unset, under normal operation when the end
-  //   of the source being iterated is reached
   CursorContinue(IDBKey key, IDBKey primary_key)
     => (IDBError? error, IDBCursorValue? value);
-
-  Prefetch(int32 count, associated IDBCallbacks callbacks);
+  Prefetch(int32 count)
+    => (IDBError? error, IDBCursorValue? value);
   PrefetchReset(int32 used_prefetches, int32 unused_prefetches);
 };
 
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
index e4a93776b..535370b 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
@@ -250,7 +250,7 @@
     {% call(property) apply_value(property, header) %}
   CSS{{animation}}Data& data = state.Style()->Access{{animation}}s();
   data.{{vector}}.clear();
-  for (auto& listValue : ToCSSValueList(value))
+  for (auto& listValue : To<CSSValueList>(value))
     data.{{vector}}.push_back(CSSToStyleMap::MapAnimation{{attribute}}(*listValue));
     {% endcall %}
   {% elif property.style_builder_template == 'svg_paint' %}
@@ -320,13 +320,13 @@
     {% call(property) apply_value(property, header) %}
   FillLayer* curr_child = &state.Style()->Access{{layer_type}}Layers();
   FillLayer* prev_child = 0;
-  if (value.IsValueList() && !value.IsImageSetValue()) {
+  const auto* value_list = DynamicTo<CSSValueList>(value);
+  if (value_list && !value.IsImageSetValue()) {
     // Walk each value and put it into a layer, creating new layers as needed.
-    const CSSValueList& valueList = ToCSSValueList(value);
-    for (unsigned int i = 0; i < valueList.length(); i++) {
+    for (unsigned int i = 0; i < value_list->length(); i++) {
       if (!curr_child)
         curr_child = prev_child->EnsureNext();
-      CSSToStyleMap::MapFill{{fill_type}}(state, curr_child, valueList.Item(i));
+      CSSToStyleMap::MapFill{{fill_type}}(state, curr_child, value_list->Item(i));
       prev_child = curr_child;
       curr_child = curr_child->Next();
     }
@@ -394,16 +394,15 @@
     {% call(property) apply_value(property, header) %}
   state.Style()->Clear{{action}}Directives();
 
-  if (!value.IsValueList()) {
+  const auto* list = DynamicTo<CSSValueList>(value);
+  if (!list) {
     DCHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueNone);
     return;
   }
 
   CounterDirectiveMap& map = state.Style()->AccessCounterDirectives();
 
-  const CSSValueList& list = ToCSSValueList(value);
-
-  for (const CSSValue* item : list) {
+  for (const CSSValue* item : *list) {
     const auto& pair = To<CSSValuePair>(*item);
     AtomicString identifier(To<CSSCustomIdentValue>(pair.First()).Value());
     int counter_value = To<CSSPrimitiveValue>(pair.Second()).GetIntValue();
diff --git a/third_party/blink/renderer/core/animation/animation_input_helpers.cc b/third_party/blink/renderer/core/animation/animation_input_helpers.cc
index dd479937..76a5eb4 100644
--- a/third_party/blink/renderer/core/animation/animation_input_helpers.cc
+++ b/third_party/blink/renderer/core/animation/animation_input_helpers.cc
@@ -253,13 +253,13 @@
   const CSSValue* value =
       CSSParser::ParseSingleValue(CSSPropertyTransitionTimingFunction, string,
                                   StrictCSSParserContext(secure_context_mode));
-  if (!value || !value->IsValueList()) {
+  const auto* value_list = DynamicTo<CSSValueList>(value);
+  if (!value_list) {
     DCHECK(!value || value->IsCSSWideKeyword());
     exception_state.ThrowTypeError("'" + string +
                                    "' is not a valid value for easing");
     return nullptr;
   }
-  const CSSValueList* value_list = ToCSSValueList(value);
   if (value_list->length() > 1) {
     exception_state.ThrowTypeError("Easing may not be set to a list of values");
     return nullptr;
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc
index 71407ff..4c4699e2 100644
--- a/third_party/blink/renderer/core/animation/css/css_animations.cc
+++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -115,9 +115,9 @@
         scoped_refptr<TimingFunction> timing_function;
         if (value.IsInheritedValue() && parent_style->Animations()) {
           timing_function = parent_style->Animations()->TimingFunctionList()[0];
-        } else if (value.IsValueList()) {
-          timing_function = CSSToStyleMap::MapAnimationTimingFunction(
-              ToCSSValueList(value).Item(0));
+        } else if (auto* value_list = DynamicTo<CSSValueList>(value)) {
+          timing_function =
+              CSSToStyleMap::MapAnimationTimingFunction(value_list->Item(0));
         } else {
           DCHECK(value.IsCSSWideKeyword());
           timing_function = CSSTimingData::InitialTimingFunction();
diff --git a/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
index 404e53c..128c3c4 100644
--- a/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
@@ -129,7 +129,7 @@
   if (!value.IsBaseValueList())
     return basic_shape_interpolation_functions::MaybeConvertCSSValue(value);
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   if (list.length() != 1)
     return nullptr;
   return basic_shape_interpolation_functions::MaybeConvertCSSValue(
diff --git a/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
index de0cc3a..2f20993e 100644
--- a/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
@@ -39,16 +39,16 @@
     const CSSValue& value,
     const StyleResolverState* state,
     ConversionCheckers&) const {
-  if (!value.IsValueList())
+  const auto* list = DynamicTo<CSSValueList>(value);
+  if (!list)
     return nullptr;
 
   ConversionCheckers null_checkers;
 
-  const CSSValueList& list = ToCSSValueList(value);
   return ListInterpolationFunctions::CreateList(
-      list.length(), [this, &list, state, &null_checkers](size_t index) {
+      list->length(), [this, list, state, &null_checkers](size_t index) {
         return this->inner_interpolation_type_->MaybeConvertValue(
-            list.Item(index), state, null_checkers);
+            list->Item(index), state, null_checkers);
       });
 }
 
diff --git a/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
index 571baf5..2c4be5a 100644
--- a/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
@@ -175,7 +175,7 @@
   if (!value.IsBaseValueList())
     return nullptr;
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   wtf_size_t length = list.length();
   std::unique_ptr<InterpolableList> interpolable_list =
       InterpolableList::Create(length);
diff --git a/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc
index f97ed973..ce4ea07 100644
--- a/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc
@@ -145,15 +145,15 @@
     const CSSValue& value,
     const StyleResolverState*,
     ConversionCheckers&) const {
-  if (!value.IsValueList()) {
+  const auto* list = DynamicTo<CSSValueList>(value);
+  if (!list) {
     return nullptr;
   }
-  const CSSValueList& list = ToCSSValueList(value);
-  wtf_size_t length = list.length();
+  wtf_size_t length = list->length();
   std::unique_ptr<InterpolableList> numbers = InterpolableList::Create(length);
   Vector<AtomicString> tags;
   for (wtf_size_t i = 0; i < length; ++i) {
-    const auto& item = To<cssvalue::CSSFontVariationValue>(list.Item(i));
+    const auto& item = To<cssvalue::CSSFontVariationValue>(list->Item(i));
     numbers->Set(i, std::make_unique<InterpolableNumber>(item.Value()));
     tags.push_back(item.Tag());
   }
diff --git a/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
index 6dae2c8a..bf46181 100644
--- a/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
@@ -120,8 +120,7 @@
     temp_list = CSSValueList::CreateCommaSeparated();
     temp_list->Append(value);
   }
-  const CSSValueList& value_list =
-      temp_list ? *temp_list : ToCSSValueList(value);
+  const auto& value_list = temp_list ? *temp_list : To<CSSValueList>(value);
 
   const wtf_size_t length = value_list.length();
   std::unique_ptr<InterpolableList> interpolable_list =
diff --git a/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
index c813b1f..1bc611a 100644
--- a/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
@@ -108,7 +108,7 @@
   if (!value.IsBaseValueList())
     return nullptr;
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   return ListInterpolationFunctions::CreateList(
       list.length(), [&list](wtf_size_t index) {
         return LengthInterpolationFunctions::MaybeConvertCSSValue(
diff --git a/third_party/blink/renderer/core/animation/css_position_axis_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_position_axis_list_interpolation_type.cc
index 9d2db0e..e02ae25 100644
--- a/third_party/blink/renderer/core/animation/css_position_axis_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_position_axis_list_interpolation_type.cc
@@ -55,7 +55,7 @@
         1, [&value](size_t) { return ConvertPositionAxisCSSValue(value); });
   }
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   return ListInterpolationFunctions::CreateList(
       list.length(), [&list](wtf_size_t index) {
         return ConvertPositionAxisCSSValue(list.Item(index));
diff --git a/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
index 7b5efd8..b7e5e95 100644
--- a/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
@@ -171,7 +171,7 @@
   if (!value.IsBaseValueList())
     return Scale().CreateInterpolationValue();
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK(list.length() >= 1 && list.length() <= 3);
 
   Scale scale(1, 1, 1);
diff --git a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
index ec601e89..5794827b 100644
--- a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
@@ -120,7 +120,7 @@
   if (!value.IsBaseValueList())
     return nullptr;
 
-  const CSSValueList& value_list = ToCSSValueList(value);
+  const auto& value_list = To<CSSValueList>(value);
   return ListInterpolationFunctions::CreateList(
       value_list.length(), [&value_list](wtf_size_t index) {
         return ShadowInterpolationFunctions::MaybeConvertCSSValue(
diff --git a/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
index 4732510..181f65e 100644
--- a/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
@@ -87,7 +87,7 @@
     temp_list->Append(value);
     list = temp_list;
   } else {
-    list = ToCSSValueList(&value);
+    list = To<CSSValueList>(&value);
   }
 
   // Flatten pairs of width/height into individual items, even for contain and
diff --git a/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc
index 4aa53c4..ed33d1de 100644
--- a/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc
@@ -167,7 +167,7 @@
   TextIndentLine line = ComputedStyleInitialValues::InitialTextIndentLine();
   TextIndentType type = ComputedStyleInitialValues::InitialTextIndentType();
 
-  for (const auto& item : ToCSSValueList(value)) {
+  for (const auto& item : To<CSSValueList>(value)) {
     auto* identifier_value = DynamicTo<CSSIdentifierValue>(item.Get());
     if (identifier_value && identifier_value->GetValueID() == CSSValueEachLine)
       line = TextIndentLine::kEachLine;
diff --git a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
index 0ff7756..635e3b9 100644
--- a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
@@ -182,9 +182,9 @@
     const StyleResolverState* state,
     ConversionCheckers& conversion_checkers) const {
   DCHECK(state);
-  if (value.IsValueList()) {
+  if (auto* list_value = DynamicTo<CSSValueList>(value)) {
     CSSLengthArray length_array;
-    for (const CSSValue* item : ToCSSValueList(value)) {
+    for (const CSSValue* item : *list_value) {
       const auto& transform_function = To<CSSFunctionValue>(*item);
       if (transform_function.FunctionType() == CSSValueMatrix ||
           transform_function.FunctionType() == CSSValueMatrix3d) {
diff --git a/third_party/blink/renderer/core/animation/css_transform_origin_interpolation_type.h b/third_party/blink/renderer/core/animation/css_transform_origin_interpolation_type.h
index 98779ab..1dd8f99d 100644
--- a/third_party/blink/renderer/core/animation/css_transform_origin_interpolation_type.h
+++ b/third_party/blink/renderer/core/animation/css_transform_origin_interpolation_type.h
@@ -23,7 +23,7 @@
   InterpolationValue MaybeConvertValue(const CSSValue& value,
                                        const StyleResolverState*,
                                        ConversionCheckers&) const final {
-    const CSSValueList& list = ToCSSValueList(value);
+    const CSSValueList& list = To<CSSValueList>(value);
     DCHECK_GE(list.length(), 2u);
     return ListInterpolationFunctions::CreateList(
         3, [&list](wtf_size_t index) {
diff --git a/third_party/blink/renderer/core/animation/css_translate_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_translate_interpolation_type.cc
index 69a4e5e..dd9842ae 100644
--- a/third_party/blink/renderer/core/animation/css_translate_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_translate_interpolation_type.cc
@@ -128,7 +128,7 @@
     return CreateNoneValue();
   }
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   if (list.length() < 1 || list.length() > 3)
     return nullptr;
 
diff --git a/third_party/blink/renderer/core/css/css_value.cc b/third_party/blink/renderer/core/css/css_value.cc
index 57448d2..5c57d38 100644
--- a/third_party/blink/renderer/core/css/css_value.cc
+++ b/third_party/blink/renderer/core/css/css_value.cc
@@ -106,7 +106,7 @@
 
 bool CSSValue::HasFailedOrCanceledSubresources() const {
   if (IsValueList())
-    return ToCSSValueList(this)->HasFailedOrCanceledSubresources();
+    return To<CSSValueList>(this)->HasFailedOrCanceledSubresources();
   if (GetClassType() == kFontFaceSrcClass)
     return To<CSSFontFaceSrcValue>(this)->HasFailedOrCanceledSubresources();
   if (GetClassType() == kImageClass)
@@ -121,7 +121,7 @@
 
 bool CSSValue::MayContainUrl() const {
   if (IsValueList())
-    return ToCSSValueList(*this).MayContainUrl();
+    return To<CSSValueList>(*this).MayContainUrl();
   return IsImageValue() || IsURIValue();
 }
 
@@ -136,7 +136,7 @@
     return;
   }
   if (IsValueList()) {
-    ToCSSValueList(*this).ReResolveUrl(document);
+    To<CSSValueList>(*this).ReResolveUrl(document);
     return;
   }
 }
@@ -348,7 +348,7 @@
     case kValuePairClass:
       return To<CSSValuePair>(this)->CustomCSSText();
     case kValueListClass:
-      return ToCSSValueList(this)->CustomCSSText();
+      return To<CSSValueList>(this)->CustomCSSText();
     case kImageSetClass:
       return To<CSSImageSetValue>(this)->CustomCSSText();
     case kCSSContentDistributionClass:
@@ -496,7 +496,7 @@
       To<CSSURIValue>(this)->~CSSURIValue();
       return;
     case kValueListClass:
-      ToCSSValueList(this)->~CSSValueList();
+      To<CSSValueList>(this)->~CSSValueList();
       return;
     case kValuePairClass:
       To<CSSValuePair>(this)->~CSSValuePair();
@@ -652,7 +652,7 @@
       To<CSSURIValue>(this)->TraceAfterDispatch(visitor);
       return;
     case kValueListClass:
-      ToCSSValueList(this)->TraceAfterDispatch(visitor);
+      To<CSSValueList>(this)->TraceAfterDispatch(visitor);
       return;
     case kValuePairClass:
       To<CSSValuePair>(this)->TraceAfterDispatch(visitor);
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h
index 22407d8..855c2239 100644
--- a/third_party/blink/renderer/core/css/css_value.h
+++ b/third_party/blink/renderer/core/css/css_value.h
@@ -297,10 +297,6 @@
   return true;
 }
 
-#define DEFINE_CSS_VALUE_TYPE_CASTS(thisType, predicate)         \
-  DEFINE_TYPE_CASTS(thisType, CSSValue, value, value->predicate, \
-                    value.predicate)
-
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_VALUE_H_
diff --git a/third_party/blink/renderer/core/css/css_value_list.h b/third_party/blink/renderer/core/css/css_value_list.h
index 090786ff..6184ad5 100644
--- a/third_party/blink/renderer/core/css/css_value_list.h
+++ b/third_party/blink/renderer/core/css/css_value_list.h
@@ -25,6 +25,7 @@
 #include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
@@ -80,7 +81,10 @@
   DISALLOW_COPY_AND_ASSIGN(CSSValueList);
 };
 
-DEFINE_CSS_VALUE_TYPE_CASTS(CSSValueList, IsValueList());
+template <>
+struct DowncastTraits<CSSValueList> {
+  static bool AllowFrom(const CSSValue& value) { return value.IsValueList(); }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/css/cssom/css_transform_value.cc b/third_party/blink/renderer/core/css/cssom/css_transform_value.cc
index 3247963..4876fa3 100644
--- a/third_party/blink/renderer/core/css/cssom/css_transform_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_transform_value.cc
@@ -32,12 +32,13 @@
 }
 
 CSSTransformValue* CSSTransformValue::FromCSSValue(const CSSValue& css_value) {
-  if (!css_value.IsValueList()) {
+  auto* css_value_list = DynamicTo<CSSValueList>(css_value);
+  if (!css_value_list) {
     // TODO(meade): Also need to check the separator here if we care.
     return nullptr;
   }
   HeapVector<Member<CSSTransformComponent>> components;
-  for (const CSSValue* value : ToCSSValueList(css_value)) {
+  for (const CSSValue* value : *css_value_list) {
     CSSTransformComponent* component =
         CSSTransformComponent::FromCSSValue(*value);
     if (!component)
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.cc b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
index 7e20dff..4e905bb 100644
--- a/third_party/blink/renderer/core/css/cssom/style_property_map.cc
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
@@ -486,20 +486,20 @@
 
   CSSValueList* current_value = nullptr;
   if (const CSSValue* css_value = GetProperty(property_id)) {
-    DCHECK(css_value->IsValueList());
-    current_value = ToCSSValueList(css_value)->Copy();
+    current_value = To<CSSValueList>(css_value)->Copy();
   } else {
     current_value = CssValueListForPropertyID(property_id);
   }
 
   const CSSValue* result = CoerceStyleValuesOrStrings(
       property, g_null_atom, nullptr, values, *execution_context);
-  if (!result || !result->IsValueList()) {
+  const auto* result_value_list = DynamicTo<CSSValueList>(result);
+  if (!result_value_list) {
     exception_state.ThrowTypeError("Invalid type for property");
     return;
   }
 
-  for (const auto& value : *ToCSSValueList(result)) {
+  for (const auto& value : *result_value_list) {
     current_value->Append(*value);
   }
 
diff --git a/third_party/blink/renderer/core/css/cssom/style_value_factory.cc b/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
index 28962379..54d70e80 100644
--- a/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
+++ b/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
@@ -110,7 +110,7 @@
         return CreateStyleValue(value);
 
       // Only single values are supported in level 1.
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       if (value_list.length() == 1U)
         return CreateStyleValue(value_list.Item(0));
       return nullptr;
@@ -119,7 +119,7 @@
     case CSSPropertyFontVariantLigatures:
     case CSSPropertyFontVariantNumeric: {
       // Only single keywords are supported in level 1.
-      if (const auto* value_list = ToCSSValueListOrNull(value)) {
+      if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
         if (value_list->length() != 1U)
           return nullptr;
         return CreateStyleValue(value_list->Item(0));
@@ -127,7 +127,7 @@
       return CreateStyleValue(value);
     }
     case CSSPropertyGridAutoFlow: {
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       // Only single keywords are supported in level 1.
       if (value_list.length() == 1U)
         return CreateStyleValue(value_list.Item(0));
@@ -146,7 +146,7 @@
     case CSSPropertyTransformOrigin:
       return CSSPositionValue::FromCSSValue(value);
     case CSSPropertyOffsetRotate: {
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       // Only single keywords are supported in level 1.
       if (value_list.length() == 1U)
         return CreateStyleValue(value_list.Item(0));
@@ -156,11 +156,10 @@
       // Computed align-items is a ValueList of either length 1 or 2.
       // Typed OM level 1 can't support "pairs", so we only return
       // a Typed OM object for length 1 lists.
-      if (value.IsValueList()) {
-        const auto& value_list = ToCSSValueList(value);
-        if (value_list.length() != 1U)
+      if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
+        if (value_list->length() != 1U)
           return nullptr;
-        return CreateStyleValue(value_list.Item(0));
+        return CreateStyleValue(value_list->Item(0));
       }
       return CreateStyleValue(value);
     }
@@ -168,7 +167,7 @@
       if (value.IsIdentifierValue())
         return CreateStyleValue(value);
 
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       // Only single keywords are supported in level 1.
       if (value_list.length() == 1U)
         return CreateStyleValue(value_list.Item(0));
@@ -178,7 +177,7 @@
       if (value.IsIdentifierValue())
         return CreateStyleValue(value);
 
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       // Only single values are supported in level 1.
       if (value_list.length() == 1U)
         return CreateStyleValue(value_list.Item(0));
@@ -186,7 +185,7 @@
     }
     case CSSPropertyTransitionProperty:
     case CSSPropertyTouchAction: {
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       // Only single values are supported in level 1.
       if (value_list.length() == 1U)
         return CreateStyleValue(value_list.Item(0));
@@ -197,7 +196,7 @@
       if (value.IsIdentifierValue())
         return CreateStyleValue(value);
 
-      const auto& value_list = ToCSSValueList(value);
+      const auto& value_list = To<CSSValueList>(value);
       if (value_list.length() == 1U) {
         const auto* ident = DynamicTo<CSSIdentifierValue>(value_list.Item(0));
         if (ident && ident->GetValueID() == CSSValueAuto)
@@ -357,7 +356,9 @@
     return style_value_vector;
   }
 
-  if (!css_value.IsValueList() ||
+  // We assume list-valued properties are always stored as a list.
+  const auto* css_value_list = DynamicTo<CSSValueList>(css_value);
+  if (!css_value_list ||
       // TODO(andruud): Custom properties claim to not be repeated, even though
       // they may be. Therefore we must ignore "IsRepeated" for custom
       // properties.
@@ -373,9 +374,7 @@
     return UnsupportedCSSValue(name, css_value);
   }
 
-  // We assume list-valued properties are always stored as a list.
-  const CSSValueList& css_value_list = ToCSSValueList(css_value);
-  for (const CSSValue* inner_value : css_value_list) {
+  for (const CSSValue* inner_value : *css_value_list) {
     style_value = CreateStyleValueWithProperty(property_id, *inner_value);
     if (!style_value)
       return UnsupportedCSSValue(name, css_value);
diff --git a/third_party/blink/renderer/core/css/font_face.cc b/third_party/blink/renderer/core/css/font_face.cc
index 63442a7..ddf99ab 100644
--- a/third_party/blink/renderer/core/css/font_face.cc
+++ b/third_party/blink/renderer/core/css/font_face.cc
@@ -84,7 +84,7 @@
 CSSFontFace* CreateCSSFontFace(FontFace* font_face,
                                const CSSValue* unicode_range) {
   Vector<UnicodeRange> ranges;
-  if (const CSSValueList* range_list = ToCSSValueList(unicode_range)) {
+  if (const auto* range_list = To<CSSValueList>(unicode_range)) {
     unsigned num_ranges = range_list->length();
     for (unsigned i = 0; i < num_ranges; i++) {
       const auto& range =
@@ -534,12 +534,12 @@
         default:
           break;
       }
-    } else if (stretch_->IsValueList()) {
+    } else if (const auto* stretch_list =
+                   DynamicTo<CSSValueList>(stretch_.Get())) {
       // Transition FontFace interpretation of parsed values from
       // CSSIdentifierValue to CSSValueList or CSSPrimitiveValue.
       // TODO(drott) crbug.com/739139: Update the parser to only produce
       // CSSPrimitiveValue or CSSValueList.
-      const CSSValueList* stretch_list = ToCSSValueList(stretch_);
       if (stretch_list->length() != 2)
         return normal_capabilities;
       const auto* stretch_from =
@@ -636,8 +636,8 @@
           NOTREACHED();
           break;
       }
-    } else if (weight_->IsValueList()) {
-      const CSSValueList* weight_list = ToCSSValueList(weight_);
+    } else if (const auto* weight_list =
+                   DynamicTo<CSSValueList>(weight_.Get())) {
       if (weight_list->length() != 2)
         return normal_capabilities;
       const auto* weight_from =
@@ -693,8 +693,7 @@
 
   // Each item in the src property's list is a single CSSFontFaceSource. Put
   // them all into a CSSFontFace.
-  DCHECK(src.IsValueList());
-  const CSSValueList& src_list = ToCSSValueList(src);
+  const auto& src_list = To<CSSValueList>(src);
   int src_length = src_list.length();
 
   for (int i = 0; i < src_length; i++) {
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
index 054684ea..87c6d401 100644
--- a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
@@ -93,36 +93,28 @@
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateColumns, "repeat(999, 20px)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 999);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit2) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateRows, "repeat(999, 20px)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 999);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit3) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateColumns, "repeat(1000000, 10%)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit4) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateRows, "repeat(1000000, 10%)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit5) {
@@ -130,9 +122,7 @@
       CSSPropertyGridTemplateColumns,
       "repeat(1000000, [first] min-content [last])",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit6) {
@@ -140,27 +130,21 @@
       CSSPropertyGridTemplateRows,
       "repeat(1000000, [first] min-content [last])",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit7) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateColumns, "repeat(1000001, auto)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit8) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateRows, "repeat(1000001, auto)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit9) {
@@ -168,9 +152,7 @@
       CSSPropertyGridTemplateColumns,
       "repeat(400000, 2em minmax(10px, max-content) 0.5fr)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 999);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit10) {
@@ -178,9 +160,7 @@
       CSSPropertyGridTemplateRows,
       "repeat(400000, 2em minmax(10px, max-content) 0.5fr)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 999);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 999);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit11) {
@@ -188,9 +168,7 @@
       CSSPropertyGridTemplateColumns,
       "repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last])",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 994);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit12) {
@@ -198,27 +176,21 @@
       CSSPropertyGridTemplateRows,
       "repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last])",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 994);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit13) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateColumns, "repeat(100000000000000000000, 10% 1fr)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit14) {
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyGridTemplateRows, "repeat(100000000000000000000, 10% 1fr)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 1000);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 1000);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit15) {
@@ -226,9 +198,7 @@
       CSSPropertyGridTemplateColumns,
       "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 994);
 }
 
 TEST(CSSPropertyParserTest, GridTrackLimit16) {
@@ -236,14 +206,11 @@
       CSSPropertyGridTemplateRows,
       "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  ASSERT_TRUE(value);
-  ASSERT_TRUE(value->IsValueList());
-  EXPECT_EQ(ComputeNumberOfTracks(ToCSSValueList(value)), 994);
+  EXPECT_EQ(ComputeNumberOfTracks(To<CSSValueList>(value)), 994);
 }
 
 static int GetGridPositionInteger(const CSSValue& value) {
-  DCHECK(value.IsValueList());
-  const auto& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK_EQ(list.length(), static_cast<size_t>(1));
   const auto& primitive_value = To<CSSPrimitiveValue>(list.Item(0));
   DCHECK(primitive_value.IsNumber());
@@ -365,8 +332,7 @@
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyScrollCustomization, "pan-down",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  DCHECK(value);
-  const CSSValueList* list = ToCSSValueList(value);
+  const auto* list = To<CSSValueList>(value);
   EXPECT_EQ(1U, list->length());
   EXPECT_EQ(CSSValuePanDown,
             To<CSSIdentifierValue>(list->Item(0U)).GetValueID());
@@ -377,7 +343,7 @@
   const CSSValue* value = CSSParser::ParseSingleValue(
       CSSPropertyScrollCustomization, "pan-left pan-y",
       StrictCSSParserContext(SecureContextMode::kSecureContext));
-  const CSSValueList* list = ToCSSValueList(value);
+  const auto* list = To<CSSValueList>(value);
   EXPECT_EQ(2U, list->length());
   EXPECT_EQ(CSSValuePanLeft,
             To<CSSIdentifierValue>(list->Item(0U)).GetValueID());
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index dc2e36c..ee0a5dac8 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -1865,7 +1865,7 @@
   if (show_vertical_bottom_left)
     vertical_radii->Append(bottom_left_radius->Item(1));
 
-  if (!vertical_radii->Equals(ToCSSValueList(list->Item(0))))
+  if (!vertical_radii->Equals(To<CSSValueList>(list->Item(0))))
     list->Append(*vertical_radii);
 
   return list;
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index c425cb4..ffe3ec7 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -606,9 +606,9 @@
     if (!list->IsBaseValueList()) {
       CSSValue* first_value = list;
       list = CSSValueList::CreateCommaSeparated();
-      ToCSSValueList(list)->Append(*first_value);
+      To<CSSValueList>(list)->Append(*first_value);
     }
-    ToCSSValueList(list)->Append(*value);
+    To<CSSValueList>(list)->Append(*value);
   } else {
     // To conserve memory we don't actually wrap a single value in a list.
     list = value;
diff --git a/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc
index f1c0063..0da8b1d4 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc
@@ -142,7 +142,7 @@
 
   ContentData* first_content = nullptr;
   ContentData* prev_content = nullptr;
-  for (auto& item : ToCSSValueList(value)) {
+  for (auto& item : To<CSSValueList>(value)) {
     ContentData* next_content = nullptr;
     if (item->IsImageGeneratorValue() || item->IsImageSetValue() ||
         item->IsImageValue()) {
diff --git a/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc
index ca8b8b8..9ce3b12 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc
@@ -113,9 +113,9 @@
 void Cursor::ApplyValue(StyleResolverState& state,
                         const CSSValue& value) const {
   state.Style()->ClearCursorList();
-  if (value.IsValueList()) {
+  if (auto* value_list = DynamicTo<CSSValueList>(value)) {
     state.Style()->SetCursor(ECursor::kAuto);
-    for (const auto& item : ToCSSValueList(value)) {
+    for (const auto& item : *value_list) {
       if (const auto* cursor =
               DynamicTo<cssvalue::CSSCursorImageValue>(*item)) {
         const CSSValue& image = cursor->ImageValue();
diff --git a/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc
index 6543dd53..be6e4e2 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc
@@ -92,7 +92,7 @@
   state.Style()->ResetPageSizeType();
   FloatSize size;
   EPageSizeType page_size_type = EPageSizeType::kAuto;
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   if (list.length() == 2) {
     // <length>{2} | <page-size> <orientation>
     const CSSValue& first = list.Item(0);
diff --git a/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc
index 7afdefc..c5b62b0 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc
@@ -101,7 +101,7 @@
   TextIndentType text_indent_type_value =
       ComputedStyleInitialValues::InitialTextIndentType();
 
-  for (auto& list_value : ToCSSValueList(value)) {
+  for (auto& list_value : To<CSSValueList>(value)) {
     if (auto* list_primitive_value =
             DynamicTo<CSSPrimitiveValue>(*list_value)) {
       length_or_percentage_value = list_primitive_value->ConvertToLength(
diff --git a/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc
index 9306ac5..0a50412 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc
@@ -98,11 +98,10 @@
 
 void WebkitTextEmphasisStyle::ApplyValue(StyleResolverState& state,
                                          const CSSValue& value) const {
-  if (value.IsValueList()) {
-    const CSSValueList& list = ToCSSValueList(value);
-    DCHECK_EQ(list.length(), 2U);
+  if (const auto* list = DynamicTo<CSSValueList>(value)) {
+    DCHECK_EQ(list->length(), 2U);
     for (unsigned i = 0; i < 2; ++i) {
-      const auto& ident_value = To<CSSIdentifierValue>(list.Item(i));
+      const auto& ident_value = To<CSSIdentifierValue>(list->Item(i));
       if (ident_value.GetValueID() == CSSValueFilled ||
           ident_value.GetValueID() == CSSValueOpen) {
         state.Style()->SetTextEmphasisFill(
diff --git a/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc
index 57e2088..b7dfd03 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc
@@ -109,8 +109,7 @@
   if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
     DCHECK_EQ(identifier_value->GetValueID(), CSSValueAuto);
   } else {
-    DCHECK(value.IsValueList());
-    for (auto& will_change_value : ToCSSValueList(value)) {
+    for (auto& will_change_value : To<CSSValueList>(value)) {
       if (auto* ident_value =
               DynamicTo<CSSCustomIdentValue>(will_change_value.Get())) {
         will_change_properties.push_back(ident_value->ValueAsPropertyID());
diff --git a/third_party/blink/renderer/core/css/property_registration.cc b/third_party/blink/renderer/core/css/property_registration.cc
index c094ac72..2bfeb21 100644
--- a/third_party/blink/renderer/core/css/property_registration.cc
+++ b/third_party/blink/renderer/core/css/property_registration.cc
@@ -61,8 +61,8 @@
                 ->NeedsVariableResolution();
   }
 
-  if (value.IsValueList()) {
-    for (const CSSValue* inner_value : ToCSSValueList(value)) {
+  if (auto* value_list = DynamicTo<CSSValueList>(value)) {
+    for (const CSSValue* inner_value : *value_list) {
       if (!ComputationallyIndependent(*inner_value))
         return false;
     }
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
index d2827d7..6c9dc83 100644
--- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
@@ -469,14 +469,14 @@
                                       CSSPropertyID property,
                                       const CSSValue& value,
                                       NinePieceImage& image) {
+  // Retrieve the border image value.
+  const auto* border_image = DynamicTo<CSSValueList>(value);
+
   // If we're not a value list, then we are "none" and don't need to alter the
   // empty image at all.
-  if (!value.IsValueList())
+  if (!border_image)
     return;
 
-  // Retrieve the border image value.
-  const CSSValueList& border_image = ToCSSValueList(value);
-
   // Set the image (this kicks off the load).
   CSSPropertyID image_property;
   if (property == CSSPropertyWebkitBorderImage)
@@ -486,28 +486,29 @@
   else
     image_property = property;
 
-  for (unsigned i = 0; i < border_image.length(); ++i) {
-    const CSSValue& current = border_image.Item(i);
+  for (unsigned i = 0; i < border_image->length(); ++i) {
+    const CSSValue& current = border_image->Item(i);
 
     if (current.IsImageValue() || current.IsImageGeneratorValue() ||
         current.IsImageSetValue()) {
       image.SetImage(state.GetStyleImage(image_property, current));
     } else if (current.IsBorderImageSliceValue()) {
       MapNinePieceImageSlice(state, current, image);
-    } else if (current.IsValueList()) {
-      const CSSValueList& slash_list = ToCSSValueList(current);
-      size_t length = slash_list.length();
+    } else if (const auto* slash_list = DynamicTo<CSSValueList>(current)) {
+      size_t length = slash_list->length();
       // Map in the image slices.
-      if (length && slash_list.Item(0).IsBorderImageSliceValue())
-        MapNinePieceImageSlice(state, slash_list.Item(0), image);
+      if (length && slash_list->Item(0).IsBorderImageSliceValue())
+        MapNinePieceImageSlice(state, slash_list->Item(0), image);
 
       // Map in the border slices.
-      if (length > 1)
-        image.SetBorderSlices(MapNinePieceImageQuad(state, slash_list.Item(1)));
+      if (length > 1) {
+        image.SetBorderSlices(
+            MapNinePieceImageQuad(state, slash_list->Item(1)));
+      }
 
       // Map in the outset.
       if (length > 2)
-        image.SetOutset(MapNinePieceImageQuad(state, slash_list.Item(2)));
+        image.SetOutset(MapNinePieceImageQuad(state, slash_list->Item(2)));
     } else if (current.IsPrimitiveValue() || current.IsValuePair()) {
       // Set the appropriate rules for stretch/round/repeat of the slices.
       MapNinePieceImageRepeat(state, current, image);
diff --git a/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc b/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
index 507537b..f96da74 100644
--- a/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
@@ -165,7 +165,7 @@
   const CSSToLengthConversionData& conversion_data =
       state.CssToLengthConversionData();
 
-  for (auto& curr_value : ToCSSValueList(in_value)) {
+  for (auto& curr_value : To<CSSValueList>(in_value)) {
     if (const auto* url_value = DynamicTo<CSSURIValue>(curr_value.Get())) {
       CountFilterUse(FilterOperation::REFERENCE, state.GetDocument());
 
@@ -256,7 +256,7 @@
                                             font_sizes, viewport_size,
                                             1);  // zoom
 
-  for (auto& curr_value : ToCSSValueList(in_value)) {
+  for (auto& curr_value : To<CSSValueList>(in_value)) {
     if (curr_value->IsURIValue())
       continue;
 
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index beb78539..08c2bf8 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -218,12 +218,10 @@
     const CSSValue& value,
     FontBuilder* font_builder,
     const Document* document_for_count) {
-  DCHECK(value.IsValueList());
-
   FontDescription::FamilyDescription desc(FontDescription::kNoFamily);
   FontFamily* curr_family = nullptr;
 
-  for (auto& family : ToCSSValueList(value)) {
+  for (auto& family : To<CSSValueList>(value)) {
     FontDescription::GenericFamilyType generic_family =
         FontDescription::kNoFamily;
     AtomicString family_name;
@@ -265,7 +263,7 @@
   if (identifier_value && identifier_value->GetValueID() == CSSValueNormal)
     return FontBuilder::InitialFeatureSettings();
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   scoped_refptr<FontFeatureSettings> settings = FontFeatureSettings::Create();
   int len = list.length();
   for (int i = 0; i < len; ++i) {
@@ -282,7 +280,7 @@
   if (identifier_value && identifier_value->GetValueID() == CSSValueNormal)
     return FontBuilder::InitialVariationSettings();
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   scoped_refptr<FontVariationSettings> settings =
       FontVariationSettings::Create();
   int len = list.length();
@@ -510,11 +508,10 @@
 FontDescription::VariantLigatures
 StyleBuilderConverter::ConvertFontVariantLigatures(StyleResolverState&,
                                                    const CSSValue& value) {
-  if (value.IsValueList()) {
+  if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
     FontDescription::VariantLigatures ligatures;
-    const CSSValueList& value_list = ToCSSValueList(value);
-    for (wtf_size_t i = 0; i < value_list.length(); ++i) {
-      const CSSValue& item = value_list.Item(i);
+    for (wtf_size_t i = 0; i < value_list->length(); ++i) {
+      const CSSValue& item = value_list->Item(i);
       switch (To<CSSIdentifierValue>(item).GetValueID()) {
         case CSSValueNoCommonLigatures:
           ligatures.common = FontDescription::kDisabledLigaturesState;
@@ -566,7 +563,7 @@
   }
 
   FontVariantNumeric variant_numeric;
-  for (const CSSValue* feature : ToCSSValueList(value)) {
+  for (const CSSValue* feature : To<CSSValueList>(value)) {
     switch (To<CSSIdentifierValue>(feature)->GetValueID()) {
       case CSSValueLiningNums:
         variant_numeric.SetNumericFigure(FontVariantNumeric::kLiningNums);
@@ -612,7 +609,7 @@
   }
 
   FontVariantEastAsian variant_east_asian;
-  for (const CSSValue* feature : ToCSSValueList(value)) {
+  for (const CSSValue* feature : To<CSSValueList>(value)) {
     switch (To<CSSIdentifierValue>(feature)->GetValueID()) {
       case CSSValueJis78:
         variant_east_asian.SetForm(FontVariantEastAsian::kJis78);
@@ -706,7 +703,7 @@
 
 GridAutoFlow StyleBuilderConverter::ConvertGridAutoFlow(StyleResolverState&,
                                                         const CSSValue& value) {
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
 
   DCHECK_GE(list.length(), 1u);
   const CSSIdentifierValue& first = To<CSSIdentifierValue>(list.Item(0));
@@ -750,7 +747,7 @@
     return position;
   }
 
-  const CSSValueList& values = ToCSSValueList(value);
+  const auto& values = To<CSSValueList>(value);
   DCHECK(values.length());
 
   bool is_span_position = false;
@@ -819,7 +816,7 @@
     OrderedNamedGridLines& ordered_named_grid_lines) {
   DCHECK(value.IsGridLineNamesValue());
 
-  for (auto& named_grid_line_value : ToCSSValueList(value)) {
+  for (auto& named_grid_line_value : To<CSSValueList>(value)) {
     String named_grid_line =
         To<CSSCustomIdentValue>(*named_grid_line_value).Value();
     NamedGridLinesMap::AddResult result =
@@ -835,9 +832,8 @@
 Vector<GridTrackSize> StyleBuilderConverter::ConvertGridTrackSizeList(
     StyleResolverState& state,
     const CSSValue& value) {
-  DCHECK(value.IsValueList());
   Vector<GridTrackSize> track_sizes;
-  for (auto& curr_value : ToCSSValueList(value)) {
+  for (auto& curr_value : To<CSSValueList>(value)) {
     DCHECK(!curr_value->IsGridLineNamesValue());
     DCHECK(!curr_value->IsGridAutoRepeatValue());
     track_sizes.push_back(ConvertGridTrackSize(state, *curr_value));
@@ -862,7 +858,7 @@
   }
 
   size_t current_named_grid_line = 0;
-  for (auto curr_value : ToCSSValueList(value)) {
+  for (auto curr_value : To<CSSValueList>(value)) {
     if (curr_value->IsGridLineNamesValue()) {
       ConvertGridLineNamesList(*curr_value, current_named_grid_line,
                                named_grid_lines, ordered_named_grid_lines);
@@ -879,7 +875,7 @@
       auto_repeat_type = auto_repeat_id == CSSValueAutoFill
                              ? AutoRepeatType::kAutoFill
                              : AutoRepeatType::kAutoFit;
-      for (auto auto_repeat_value : ToCSSValueList(*curr_value)) {
+      for (auto auto_repeat_value : To<CSSValueList>(*curr_value)) {
         if (auto_repeat_value->IsGridLineNamesValue()) {
           ConvertGridLineNamesList(*auto_repeat_value, auto_repeat_index,
                                    auto_repeat_named_grid_lines,
@@ -1109,7 +1105,7 @@
     const CSSValue& value) {
   StyleOffsetRotation result(0, OffsetRotationType::kFixed);
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK(list.length() == 1 || list.length() == 2);
   for (const auto& item : list) {
     auto* identifier_value = DynamicTo<CSSIdentifierValue>(item.Get());
@@ -1165,18 +1161,17 @@
 EPaintOrder StyleBuilderConverter::ConvertPaintOrder(
     StyleResolverState&,
     const CSSValue& css_paint_order) {
-  if (css_paint_order.IsValueList()) {
-    const CSSValueList& order_type_list = ToCSSValueList(css_paint_order);
-    switch (To<CSSIdentifierValue>(order_type_list.Item(0)).GetValueID()) {
+  if (const auto* order_type_list = DynamicTo<CSSValueList>(css_paint_order)) {
+    switch (To<CSSIdentifierValue>(order_type_list->Item(0)).GetValueID()) {
       case CSSValueFill:
-        return order_type_list.length() > 1 ? kPaintOrderFillMarkersStroke
-                                            : kPaintOrderFillStrokeMarkers;
+        return order_type_list->length() > 1 ? kPaintOrderFillMarkersStroke
+                                             : kPaintOrderFillStrokeMarkers;
       case CSSValueStroke:
-        return order_type_list.length() > 1 ? kPaintOrderStrokeMarkersFill
-                                            : kPaintOrderStrokeFillMarkers;
+        return order_type_list->length() > 1 ? kPaintOrderStrokeMarkersFill
+                                             : kPaintOrderStrokeFillMarkers;
       case CSSValueMarkers:
-        return order_type_list.length() > 1 ? kPaintOrderMarkersStrokeFill
-                                            : kPaintOrderMarkersFillStroke;
+        return order_type_list->length() > 1 ? kPaintOrderMarkersStrokeFill
+                                             : kPaintOrderMarkersFillStroke;
       default:
         NOTREACHED();
         return kPaintOrderNormal;
@@ -1198,12 +1193,11 @@
 scoped_refptr<QuotesData> StyleBuilderConverter::ConvertQuotes(
     StyleResolverState&,
     const CSSValue& value) {
-  if (value.IsValueList()) {
-    const CSSValueList& list = ToCSSValueList(value);
+  if (const auto* list = DynamicTo<CSSValueList>(value)) {
     scoped_refptr<QuotesData> quotes = QuotesData::Create();
-    for (wtf_size_t i = 0; i < list.length(); i += 2) {
-      String start_quote = To<CSSStringValue>(list.Item(i)).Value();
-      String end_quote = To<CSSStringValue>(list.Item(i + 1)).Value();
+    for (wtf_size_t i = 0; i < list->length(); i += 2) {
+      String start_quote = To<CSSStringValue>(list->Item(i)).Value();
+      String end_quote = To<CSSStringValue>(list->Item(i + 1)).Value();
       quotes->AddPair(std::make_pair(start_quote, end_quote));
     }
     return quotes;
@@ -1279,7 +1273,7 @@
   }
 
   ShadowDataVector shadows;
-  for (const auto& item : ToCSSValueList(value)) {
+  for (const auto& item : To<CSSValueList>(value)) {
     shadows.push_back(
         ConvertShadow(state.CssToLengthConversionData(), &state, *item));
   }
@@ -1301,7 +1295,7 @@
 
   scoped_refptr<BasicShape> shape;
   CSSBoxType css_box = CSSBoxType::kMissing;
-  const CSSValueList& value_list = ToCSSValueList(value);
+  const auto& value_list = To<CSSValueList>(value);
   for (unsigned i = 0; i < value_list.length(); ++i) {
     const CSSValue& item_value = value_list.Item(i);
     if (item_value.IsBasicShapeValue()) {
@@ -1330,16 +1324,15 @@
 scoped_refptr<SVGDashArray> StyleBuilderConverter::ConvertStrokeDasharray(
     StyleResolverState& state,
     const CSSValue& value) {
-  if (!value.IsValueList())
+  const auto* dashes = DynamicTo<CSSValueList>(value);
+  if (!dashes)
     return SVGComputedStyle::InitialStrokeDashArray();
 
-  const CSSValueList& dashes = ToCSSValueList(value);
-
   scoped_refptr<SVGDashArray> array = SVGDashArray::Create();
-  wtf_size_t length = dashes.length();
+  wtf_size_t length = dashes->length();
   for (wtf_size_t i = 0; i < length; ++i) {
     array->push_back(
-        ConvertLength(state, To<CSSPrimitiveValue>(dashes.Item(i))));
+        ConvertLength(state, To<CSSPrimitiveValue>(dashes->Item(i))));
   }
 
   return array;
@@ -1374,11 +1367,10 @@
                                                 const CSSValue& value) {
   const CSSValue* local_value = &value;
   SVGPaint paint;
-  if (value.IsValueList()) {
-    const CSSValueList& list = ToCSSValueList(value);
-    DCHECK_EQ(list.length(), 2u);
-    paint.resource = ConvertElementReference(state, list.Item(0));
-    local_value = &list.Item(1);
+  if (const auto* list = DynamicTo<CSSValueList>(value)) {
+    DCHECK_EQ(list->length(), 2u);
+    paint.resource = ConvertElementReference(state, list->Item(0));
+    local_value = &list->Item(1);
   }
 
   if (local_value->IsURIValue()) {
@@ -1407,7 +1399,7 @@
 TextEmphasisPosition StyleBuilderConverter::ConvertTextTextEmphasisPosition(
     StyleResolverState& state,
     const CSSValue& value) {
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   CSSValueID first = To<CSSIdentifierValue>(list.Item(0)).GetValueID();
   CSSValueID second = To<CSSIdentifierValue>(list.Item(1)).GetValueID();
   if (first == CSSValueOver && second == CSSValueRight)
@@ -1458,8 +1450,8 @@
         To<CSSIdentifierValue>(identifier).ConvertTo<TextUnderlinePosition>();
   };
 
-  if (value.IsValueList()) {
-    for (auto& entry : ToCSSValueList(value)) {
+  if (auto* value_list = DynamicTo<CSSValueList>(value)) {
+    for (auto& entry : *value_list) {
       process(*entry);
     }
   } else {
@@ -1478,7 +1470,7 @@
 TransformOrigin StyleBuilderConverter::ConvertTransformOrigin(
     StyleResolverState& state,
     const CSSValue& value) {
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK_GE(list.length(), 2u);
   DCHECK(list.Item(0).IsPrimitiveValue() || list.Item(0).IsIdentifierValue());
   DCHECK(list.Item(1).IsPrimitiveValue() || list.Item(1).IsIdentifierValue());
@@ -1544,7 +1536,7 @@
     DCHECK_EQ(identifier_value->GetValueID(), CSSValueNone);
     return nullptr;
   }
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK_LE(list.length(), 3u);
   Length tx = ConvertLength(state, list.Item(0));
   Length ty = Length::Fixed(0);
@@ -1565,7 +1557,7 @@
     return Rotation(FloatPoint3D(0, 0, 1), 0);
   }
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK(list.length() == 1 || list.length() == 2);
   double x = 0;
   double y = 0;
@@ -1602,7 +1594,7 @@
     return nullptr;
   }
 
-  const CSSValueList& list = ToCSSValueList(value);
+  const auto& list = To<CSSValueList>(value);
   DCHECK_LE(list.length(), 3u);
   double sx = To<CSSPrimitiveValue>(list.Item(0)).GetDoubleValue();
   double sy = sx;
@@ -1650,17 +1642,16 @@
   if (const auto* function_value = DynamicTo<CSSFunctionValue>(value)) {
     CSSFunctionValue* new_function =
         CSSFunctionValue::Create(function_value->FunctionType());
-    for (const CSSValue* inner_value : ToCSSValueList(value)) {
+    for (const CSSValue* inner_value : To<CSSValueList>(value)) {
       new_function->Append(ComputeRegisteredPropertyValue(
           document, css_to_length_conversion_data, *inner_value));
     }
     return *new_function;
   }
 
-  if (value.IsValueList()) {
-    const CSSValueList& old_list = ToCSSValueList(value);
-    CSSValueList* new_list = CSSValueList::CreateWithSeparatorFrom(old_list);
-    for (const CSSValue* inner_value : old_list) {
+  if (const auto* old_list = DynamicTo<CSSValueList>(value)) {
+    CSSValueList* new_list = CSSValueList::CreateWithSeparatorFrom(*old_list);
+    for (const CSSValue* inner_value : *old_list) {
       new_list->Append(ComputeRegisteredPropertyValue(
           document, css_to_length_conversion_data, *inner_value));
     }
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
index 2eedb03..e3460da 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
@@ -287,7 +287,7 @@
   auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
   if (identifier_value && identifier_value->GetValueID() == CSSValueNone)
     return flags;
-  for (auto& flag_value : ToCSSValueList(value))
+  for (auto& flag_value : To<CSSValueList>(value))
     flags |= To<CSSIdentifierValue>(*flag_value).ConvertTo<T>();
   return flags;
 }
diff --git a/third_party/blink/renderer/core/css/resolver/transform_builder.cc b/third_party/blink/renderer/core/css/resolver/transform_builder.cc
index 0e35559..72424f1 100644
--- a/third_party/blink/renderer/core/css/resolver/transform_builder.cc
+++ b/third_party/blink/renderer/core/css/resolver/transform_builder.cc
@@ -131,13 +131,14 @@
     const CSSValue& in_value,
     const CSSToLengthConversionData& conversion_data) {
   TransformOperations operations;
-  if (!in_value.IsValueList()) {
+  auto* in_value_list = DynamicTo<CSSValueList>(in_value);
+  if (!in_value_list) {
     DCHECK_EQ(To<CSSIdentifierValue>(in_value).GetValueID(), CSSValueNone);
     return operations;
   }
 
   float zoom_factor = conversion_data.Zoom();
-  for (auto& value : ToCSSValueList(in_value)) {
+  for (auto& value : *in_value_list) {
     const auto* transform_value = To<CSSFunctionValue>(value.Get());
     TransformOperation::OperationType transform_type =
         GetTransformOperationType(transform_value->FunctionType());
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc
index 3f96d69..43eba69 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -889,7 +889,7 @@
   for (unsigned i = 0; i < size; i++) {
     values[i] = property_set_.GetPropertyCSSValue(*shorthand.properties()[i]);
     if (values[i]->IsBaseValueList()) {
-      const CSSValueList* value_list = ToCSSValueList(values[i]);
+      const CSSValueList* value_list = To<CSSValueList>(values[i].Get());
       num_layers = std::max(num_layers, value_list->length());
     }
   }
@@ -911,8 +911,8 @@
 
       // Get a CSSValue for this property and layer.
       if (values[property_index]->IsBaseValueList()) {
-        const CSSValueList* property_values =
-            ToCSSValueList(values[property_index]);
+        const auto* property_values =
+            To<CSSValueList>(values[property_index].Get());
         // There might not be an item for this layer for this property.
         if (layer < property_values->length())
           value = &property_values->Item(layer);
@@ -935,10 +935,10 @@
                    CSSPropertyBackgroundRepeatY) ||
                shorthand.properties()[property_index + 1]->IDEquals(
                    CSSPropertyWebkitMaskRepeatY));
+        auto* value_list =
+            DynamicTo<CSSValueList>(values[property_index + 1].Get());
         const CSSValue& y_value =
-            values[property_index + 1]->IsValueList()
-                ? ToCSSValueList(values[property_index + 1])->Item(layer)
-                : *values[property_index + 1];
+            value_list ? value_list->Item(layer) : *values[property_index + 1];
 
         // FIXME: At some point we need to fix this code to avoid returning an
         // invalid shorthand, since some longhand combinations are not
@@ -1116,23 +1116,19 @@
   const CSSValue& repeat_y =
       *property_set_.GetPropertyCSSValue(GetCSSPropertyBackgroundRepeatY());
 
-  const CSSValueList* repeat_x_list = nullptr;
+  const auto* repeat_x_list = DynamicTo<CSSValueList>(repeat_x);
   int repeat_x_length = 1;
-  if (repeat_x.IsValueList()) {
-    repeat_x_list = &ToCSSValueList(repeat_x);
+  if (repeat_x_list)
     repeat_x_length = repeat_x_list->length();
-  } else if (!repeat_x.IsIdentifierValue()) {
+  else if (!repeat_x.IsIdentifierValue())
     return String();
-  }
 
-  const CSSValueList* repeat_y_list = nullptr;
+  const auto* repeat_y_list = DynamicTo<CSSValueList>(repeat_y);
   int repeat_y_length = 1;
-  if (repeat_y.IsValueList()) {
-    repeat_y_list = &ToCSSValueList(repeat_y);
+  if (repeat_y_list)
     repeat_y_length = repeat_y_list->length();
-  } else if (!repeat_y.IsIdentifierValue()) {
+  else if (!repeat_y.IsIdentifierValue())
     return String();
-  }
 
   size_t shorthand_length =
       lowestCommonMultiple(repeat_x_length, repeat_y_length);
diff --git a/third_party/blink/renderer/core/editing/commands/style_commands.cc b/third_party/blink/renderer/core/editing/commands/style_commands.cc
index f2bd307..6bc15205 100644
--- a/third_party/blink/renderer/core/editing/commands/style_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/style_commands.cc
@@ -285,9 +285,9 @@
                                                const CSSValue& value) {
   const CSSValue& selected_css_value =
       *selection_style.Style()->GetPropertyCSSValue(property_id);
-  if (selected_css_value.IsValueList()) {
+  if (IsA<CSSValueList>(selected_css_value)) {
     CSSValueList& selected_css_value_list =
-        *ToCSSValueList(selected_css_value).Copy();
+        *To<CSSValueList>(selected_css_value).Copy();
     if (!selected_css_value_list.RemoveAll(value))
       selected_css_value_list.Append(value);
     if (selected_css_value_list.length())
diff --git a/third_party/blink/renderer/core/editing/editing_style.cc b/third_party/blink/renderer/core/editing/editing_style.cc
index 6b2a173..36e0a9fb 100644
--- a/third_party/blink/renderer/core/editing/editing_style.cc
+++ b/third_party/blink/renderer/core/editing/editing_style.cc
@@ -293,8 +293,10 @@
       style->GetPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
   if (!style_value)
     style_value = style->GetPropertyCSSValue(CSSPropertyTextDecorationLine);
-  return Matches(element) && style_value && style_value->IsValueList() &&
-         ToCSSValueList(style_value)->HasValue(*identifier_value_);
+  if (!Matches(element))
+    return false;
+  auto* style_value_list = DynamicTo<CSSValueList>(style_value);
+  return style_value_list && style_value_list->HasValue(*identifier_value_);
 }
 
 class HTMLAttributeEquivalent : public HTMLElementEquivalent {
@@ -1362,12 +1364,13 @@
     const CSSValue* value = mutable_style_->GetPropertyCSSValue(property.Id());
 
     // text decorations never override values
+    const auto* property_value_list = DynamicTo<CSSValueList>(property.Value());
     if ((property.Id() == CSSPropertyTextDecorationLine ||
          property.Id() == CSSPropertyWebkitTextDecorationsInEffect) &&
-        property.Value().IsValueList() && value) {
-      if (value->IsValueList()) {
-        const CSSValueList& result = MergeTextDecorationValues(
-            *ToCSSValueList(value), ToCSSValueList(property.Value()));
+        property_value_list && value) {
+      if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
+        const CSSValueList& result =
+            MergeTextDecorationValues(*value_list, *property_value_list);
         mutable_style_->SetProperty(property.Id(), result,
                                     property.IsImportant());
         continue;
@@ -1670,12 +1673,13 @@
   // property is always a CSSValueList.
   const CSSValue* text_decoration =
       style->GetPropertyCSSValue(CSSPropertyTextDecorationLine);
-  if (text_decoration && text_decoration->IsValueList()) {
+  if (const auto* text_decoration_value_list =
+          DynamicTo<CSSValueList>(text_decoration)) {
     DEFINE_STATIC_LOCAL(Persistent<CSSIdentifierValue>, underline,
                         (CSSIdentifierValue::Create(CSSValueUnderline)));
     DEFINE_STATIC_LOCAL(Persistent<CSSIdentifierValue>, line_through,
                         (CSSIdentifierValue::Create(CSSValueLineThrough)));
-    CSSValueList* new_text_decoration = ToCSSValueList(text_decoration)->Copy();
+    CSSValueList* new_text_decoration = text_decoration_value_list->Copy();
     if (new_text_decoration->RemoveAll(*underline))
       apply_underline_ = true;
     if (new_text_decoration->RemoveAll(*line_through))
@@ -1729,13 +1733,14 @@
                                 const CSSValue* ref_text_decoration,
                                 SecureContextMode secure_context_mode) {
   const CSSValue* text_decoration = style->GetPropertyCSSValue(property_id);
-  if (!text_decoration || !text_decoration->IsValueList() ||
-      !ref_text_decoration || !ref_text_decoration->IsValueList())
+  const auto* values_in_text_decoration =
+      DynamicTo<CSSValueList>(text_decoration);
+  const auto* values_in_ref_text_decoration =
+      DynamicTo<CSSValueList>(ref_text_decoration);
+  if (!values_in_text_decoration || !values_in_ref_text_decoration)
     return;
 
-  CSSValueList* new_text_decoration = ToCSSValueList(text_decoration)->Copy();
-  const CSSValueList* values_in_ref_text_decoration =
-      ToCSSValueList(ref_text_decoration);
+  CSSValueList* new_text_decoration = values_in_text_decoration->Copy();
 
   for (wtf_size_t i = 0; i < values_in_ref_text_decoration->length(); i++)
     new_text_decoration->RemoveAll(values_in_ref_text_decoration->Item(i));
diff --git a/third_party/blink/renderer/core/editing/selection_modifier_character.cc b/third_party/blink/renderer/core/editing/selection_modifier_character.cc
index 648ffd3..a88c0db 100644
--- a/third_party/blink/renderer/core/editing/selection_modifier_character.cc
+++ b/third_party/blink/renderer/core/editing/selection_modifier_character.cc
@@ -38,6 +38,8 @@
 #include "third_party/blink/renderer/core/editing/visible_units.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h"
@@ -159,6 +161,18 @@
     DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
     return caret_navigator.LeftPositionOf(caret_position);
   }
+
+  static NGCaretNavigator::Position MostBackwardPositionInFirstLine(
+      const NGCaretNavigator& caret_navigator) {
+    DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
+    return caret_navigator.RightmostPositionInFirstLine();
+  }
+
+  static NGCaretNavigator::Position MostBackwardPositionInLastLine(
+      const NGCaretNavigator& caret_navigator) {
+    DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
+    return caret_navigator.RightmostPositionInLastLine();
+  }
 };
 
 // The traversal strategy for |RightPositionOf()|.
@@ -272,6 +286,18 @@
     DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
     return caret_navigator.RightPositionOf(caret_position);
   }
+
+  static NGCaretNavigator::Position MostBackwardPositionInFirstLine(
+      const NGCaretNavigator& caret_navigator) {
+    DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
+    return caret_navigator.LeftmostPositionInFirstLine();
+  }
+
+  static NGCaretNavigator::Position MostBackwardPositionInLastLine(
+      const NGCaretNavigator& caret_navigator) {
+    DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
+    return caret_navigator.LeftmostPositionInLastLine();
+  }
 };
 
 template <typename Traversal>
@@ -496,8 +522,64 @@
 }
 
 template <typename Strategy, typename Traversal>
+PositionWithAffinityTemplate<Strategy> TraverseIntoChildContext(
+    const PositionTemplate<Strategy>& position) {
+  DCHECK(position.IsNotNull());
+  DCHECK(position.IsBeforeAnchor() || position.IsAfterAnchor()) << position;
+  DCHECK(position.AnchorNode()->GetLayoutObject()) << position;
+  DCHECK(position.AnchorNode()->GetLayoutObject()->IsLayoutBlockFlow())
+      << position;
+
+  LayoutBlockFlow& target_block =
+      *ToLayoutBlockFlow(position.AnchorNode()->GetLayoutObject());
+
+  if (!target_block.IsLayoutNGMixin()) {
+    // In most cases, we reach here by crossing editing boundary, in which case
+    // returning null position suffices.
+    // TODO(xiaochengh): Investigate if there are other cases that need a
+    // non-trivial legacy fallback.
+    return PositionWithAffinityTemplate<Strategy>();
+  }
+
+  if (!target_block.ChildrenInline() || !target_block.HasNGInlineNodeData() ||
+      !target_block.GetNGInlineNodeData()->text_content.length()) {
+    // TODO(xiaochengh): Implement when |target_block| has its own child blocks,
+    // or when |target_block| is empty.
+    return PositionWithAffinityTemplate<Strategy>();
+  }
+
+  NGCaretNavigator caret_navigator(target_block);
+  DCHECK(caret_navigator.GetText().length());
+
+  const NGCaretNavigator::Position position_in_target =
+      position.IsBeforeAnchor()
+          ? Traversal::MostBackwardPositionInFirstLine(caret_navigator)
+          : Traversal::MostBackwardPositionInLastLine(caret_navigator);
+
+  // When moving into inline block, the caret moves over the first character
+  // seamlessly as if there's no inline block boundary. For example:
+  // RightPositionOf(foo|<inline-block>bar</inline-block>)
+  // -> foo<inline-block>b|ar</inline-block>
+  const NGCaretNavigator::VisualCaretMovementResult result_position =
+      Traversal::ForwardPositionOf(caret_navigator, position_in_target);
+
+  if (!result_position.IsWithinContext()) {
+    // TODO(xiaochengh): We reach here if |target_block| starts with an
+    // enterable child context. Fix it with proper block navigation.
+    // Also investigate if we reach here for other reasons.
+    return PositionWithAffinityTemplate<Strategy>();
+  }
+
+  const NGOffsetMapping* mapping =
+      NGInlineNode::GetOffsetMapping(&target_block);
+  return FromPositionInDOMTree<Strategy>(
+      mapping->GetPositionWithAffinity(*result_position.position));
+}
+
+template <typename Strategy, typename Traversal>
 PositionWithAffinityTemplate<Strategy> TraverseWithBidiCaretAffinity(
-    const PositionWithAffinityTemplate<Strategy> start_position_with_affinity) {
+    const PositionWithAffinityTemplate<Strategy>&
+        start_position_with_affinity) {
   const PositionTemplate<Strategy> start_position =
       start_position_with_affinity.GetPosition();
   const Position start_position_in_dom = ToPositionInDOMTree(start_position);
@@ -547,6 +629,16 @@
         result_caret_position.position.value()));
   }
 
+  if (result_caret_position.HasEnteredChildContext()) {
+    DCHECK(result_caret_position.position.has_value());
+    const PositionTemplate<Strategy> outside_child_context =
+        FromPositionInDOMTree<Strategy>(
+            mapping->GetPositionWithAffinity(*result_caret_position.position))
+            .GetPosition();
+
+    return TraverseIntoChildContext<Strategy, Traversal>(outside_child_context);
+  }
+
   // We reach here if we need to move out of the current block.
   if (result_caret_position.IsBeforeContext()) {
     // TODO(xiaochengh): Move to the visual end of the previous block.
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
index 73736ec..d91b304 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -492,12 +492,14 @@
     it.value->DispatchBufferedTouchEvents();
 }
 
-bool WebDevToolsAgentImpl::HandleInputEvent(const WebInputEvent& event) {
+WebInputEventResult WebDevToolsAgentImpl::HandleInputEvent(
+    const WebInputEvent& event) {
   for (auto& it : overlay_agents_) {
-    if (it.value->HandleInputEvent(event))
-      return true;
+    auto result = it.value->HandleInputEvent(event);
+    if (result != WebInputEventResult::kNotHandled)
+      return result;
   }
-  return false;
+  return WebInputEventResult::kNotHandled;
 }
 
 String WebDevToolsAgentImpl::NavigationInitiatorInfo(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
index 8039d45..a55e5c52 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
@@ -33,6 +33,7 @@
 
 #include <memory>
 
+#include "third_party/blink/public/platform/web_input_event_result.h"
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/inspector/devtools_agent.h"
@@ -85,7 +86,7 @@
   void UpdateOverlays();
   void PaintOverlays(GraphicsContext&);  // For CompositeAfterPaint.
 
-  bool HandleInputEvent(const WebInputEvent&);
+  WebInputEventResult HandleInputEvent(const WebInputEvent&);
   void DispatchBufferedTouchEvents();
   void BindRequest(mojom::blink::DevToolsAgentHostAssociatedPtrInfo,
                    mojom::blink::DevToolsAgentAssociatedRequest);
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 9b583fa..bff13003 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1685,8 +1685,9 @@
     return WebInputEventResult::kHandledSuppressed;
 
   if (WebDevToolsAgentImpl* devtools = MainFrameDevToolsAgentImpl()) {
-    if (devtools->HandleInputEvent(input_event))
-      return WebInputEventResult::kHandledSuppressed;
+    auto result = devtools->HandleInputEvent(input_event);
+    if (result != WebInputEventResult::kNotHandled)
+      return result;
   }
 
   // Report the event to be NOT processed by WebKit, so that the browser can
diff --git a/third_party/blink/renderer/core/frame/frame_serializer.cc b/third_party/blink/renderer/core/frame/frame_serializer.cc
index d443704..e2333d9 100644
--- a/third_party/blink/renderer/core/frame/frame_serializer.cc
+++ b/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -558,10 +558,9 @@
       return;
 
     AddFontToResources(font_face_src_value->Fetch(&document, nullptr));
-  } else if (css_value.IsValueList()) {
-    const CSSValueList& css_value_list = ToCSSValueList(css_value);
-    for (unsigned i = 0; i < css_value_list.length(); i++)
-      RetrieveResourcesForCSSValue(css_value_list.Item(i), document);
+  } else if (const auto* css_value_list = DynamicTo<CSSValueList>(css_value)) {
+    for (unsigned i = 0; i < css_value_list->length(); i++)
+      RetrieveResourcesForCSSValue(css_value_list->Item(i), document);
   }
 }
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 70ccd91..2cb2430 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -414,8 +414,9 @@
 
   if (LocalRootImpl()) {
     if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl()) {
-      if (devtools->HandleInputEvent(input_event))
-        return WebInputEventResult::kHandledSuppressed;
+      auto result = devtools->HandleInputEvent(input_event);
+      if (result != WebInputEventResult::kNotHandled)
+        return result;
     }
   }
 
diff --git a/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc b/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
index b516155..87e251c 100644
--- a/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
+++ b/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
@@ -488,7 +488,7 @@
     return;
   }
 
-  if (TransformBuilder::HasRelativeLengths(ToCSSValueList(*value))) {
+  if (TransformBuilder::HasRelativeLengths(To<CSSValueList>(*value))) {
     exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
                                       "Lengths must be absolute, not relative");
     return;
diff --git a/third_party/blink/renderer/core/html/html_font_element.cc b/third_party/blink/renderer/core/html/html_font_element.cc
index d61a02c0..fb2526c 100644
--- a/third_party/blink/renderer/core/html/html_font_element.cc
+++ b/third_party/blink/renderer/core/html/html_font_element.cc
@@ -128,8 +128,8 @@
     const CSSValue* parsed_value = CSSParser::ParseSingleValue(
         CSSPropertyFontFamily, string,
         StrictCSSParserContext(secure_context_mode));
-    if (parsed_value && parsed_value->IsValueList())
-      entry.stored_value->value = ToCSSValueList(parsed_value);
+    if (auto* parsed_value_list = DynamicTo<CSSValueList>(parsed_value))
+      entry.stored_value->value = parsed_value_list;
   }
   return entry.stored_value->value;
 }
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index 8d4902b..621a17c 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -31,6 +31,7 @@
 #include <algorithm>
 #include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/auto_reset.h"
 #include "build/build_config.h"
@@ -143,6 +144,175 @@
 
 }  // namespace
 
+// InspectTool -----------------------------------------------------------------
+
+void InspectTool::Init(InspectorOverlayAgent* overlay,
+                       OverlayFrontend* frontend) {
+  overlay_ = overlay;
+  frontend_ = frontend;
+  DoInit();
+}
+
+bool InspectTool::HandleMouseDown(const WebMouseEvent&,
+                                  bool* swallow_next_mouse_up) {
+  return false;
+}
+
+bool InspectTool::HandleMouseUp(const WebMouseEvent&) {
+  return false;
+}
+
+bool InspectTool::HandleMouseMove(const WebMouseEvent&) {
+  return false;
+}
+
+bool InspectTool::HandleGestureTapEvent(const WebGestureEvent&) {
+  return false;
+}
+
+bool InspectTool::HandlePointerEvent(const WebPointerEvent&) {
+  return false;
+}
+
+bool InspectTool::HandleKeyboardEvent(const WebKeyboardEvent&,
+                                      bool* swallow_next_escape_up) {
+  return false;
+}
+
+void InspectTool::Trace(blink::Visitor* visitor) {
+  visitor->Trace(overlay_);
+}
+
+// SearchingForNodeTool --------------------------------------------------------
+
+class SearchingForNodeTool : public InspectTool {
+ public:
+  SearchingForNodeTool(InspectorDOMAgent* dom_agent,
+                       bool ua_shadow,
+                       const String& highlight_config);
+
+ private:
+  bool HandleMouseDown(const WebMouseEvent& event,
+                       bool* swallow_next_mouse_up) override;
+  bool HandleMouseMove(const WebMouseEvent& event) override;
+  bool HandleGestureTapEvent(const WebGestureEvent&) override;
+  bool HandlePointerEvent(const WebPointerEvent&) override;
+  void NodeHighlightRequested(Node*);
+  void Trace(blink::Visitor* visitor) override;
+
+  Member<InspectorDOMAgent> dom_agent_;
+  bool ua_shadow_;
+  Member<Node> hovered_node_for_inspect_mode_;
+  std::unique_ptr<InspectorHighlightConfig> inspect_mode_highlight_config_;
+};
+
+SearchingForNodeTool::SearchingForNodeTool(InspectorDOMAgent* dom_agent,
+                                           bool ua_shadow,
+                                           const String& config)
+    : dom_agent_(dom_agent), ua_shadow_(ua_shadow) {
+  std::unique_ptr<protocol::Value> value =
+      protocol::StringUtil::parseJSON(config);
+  if (!value)
+    return;
+  protocol::ErrorSupport errors;
+  std::unique_ptr<protocol::Overlay::HighlightConfig> highlight_config =
+      protocol::Overlay::HighlightConfig::fromValue(value.get(), &errors);
+  overlay_->HighlightConfigFromInspectorObject(std::move(highlight_config),
+                                               &inspect_mode_highlight_config_);
+}
+
+void SearchingForNodeTool::Trace(blink::Visitor* visitor) {
+  InspectTool::Trace(visitor);
+  visitor->Trace(dom_agent_);
+  visitor->Trace(hovered_node_for_inspect_mode_);
+}
+
+// ScreenshotTool --------------------------------------------------------------
+
+class ScreenshotTool : public InspectTool {
+ public:
+  ScreenshotTool() = default;
+
+ private:
+  bool HandleKeyboardEvent(const WebKeyboardEvent&,
+                           bool* swallow_next_escape_up) override;
+  bool HandleMouseDown(const WebMouseEvent& event,
+                       bool* swallow_next_mouse_up) override;
+  bool HandleMouseMove(const WebMouseEvent& event) override;
+  bool HandleMouseUp(const WebMouseEvent& event) override;
+  void Draw(float scale) override;
+  void DoInit() override;
+
+  IntPoint screenshot_anchor_;
+  IntPoint screenshot_position_;
+};
+
+void ScreenshotTool::DoInit() {
+  auto& client = overlay_->GetFrame()->GetPage()->GetChromeClient();
+  client.SetCursorOverridden(false);
+  client.SetCursor(CrossCursor(), overlay_->GetFrame());
+  client.SetCursorOverridden(true);
+}
+
+bool ScreenshotTool::HandleKeyboardEvent(const WebKeyboardEvent& event,
+                                         bool* swallow_next_escape_up) {
+  if (event.GetType() == WebInputEvent::kRawKeyDown &&
+      event.windows_key_code == VKEY_ESCAPE &&
+      screenshot_anchor_ != IntPoint::Zero()) {
+    screenshot_anchor_ = IntPoint::Zero();
+    *swallow_next_escape_up = true;
+    return true;
+  }
+  return false;
+}
+
+bool ScreenshotTool::HandleMouseDown(const WebMouseEvent& event,
+                                     bool* swallow_next_mouse_up) {
+  screenshot_anchor_ = RoundedIntPoint(event.PositionInRootFrame());
+  screenshot_position_ = screenshot_anchor_;
+  return true;
+}
+
+bool ScreenshotTool::HandleMouseMove(const WebMouseEvent& event) {
+  screenshot_position_ = RoundedIntPoint(event.PositionInRootFrame());
+  return true;
+}
+
+void ScreenshotTool::Draw(float scale) {
+  if (screenshot_anchor_ == IntPoint::Zero())
+    return;
+  const VisualViewport& visual_viewport =
+      overlay_->GetFrame()->GetPage()->GetVisualViewport();
+  IntPoint p1 = visual_viewport.RootFrameToViewport(screenshot_anchor_);
+  IntPoint p2 = visual_viewport.RootFrameToViewport(screenshot_position_);
+  p1.Scale(scale, scale);
+  p2.Scale(scale, scale);
+  std::unique_ptr<protocol::DictionaryValue> data =
+      protocol::DictionaryValue::create();
+  data->setInteger("x1", p1.X());
+  data->setInteger("y1", p1.Y());
+  data->setInteger("x2", p2.X());
+  data->setInteger("y2", p2.Y());
+  overlay_->EvaluateInOverlay("drawScreenshotBorder", std::move(data));
+}
+
+// PausedInDebuggerTool --------------------------------------------------------
+
+class PausedInDebuggerTool : public InspectTool {
+ public:
+  PausedInDebuggerTool(const String& message) : message_(message) {}
+
+ private:
+  void Draw(float scale) override;
+  String message_;
+};
+
+void PausedInDebuggerTool::Draw(float scale) {
+  overlay_->EvaluateInOverlay("drawPausedInDebuggerMessage", message_);
+}
+
+// InspectorOverlayAgent -------------------------------------------------------
+
 class InspectorOverlayAgent::InspectorPageOverlayDelegate final
     : public FrameOverlay::Delegate,
       public cc::ContentLayerClient {
@@ -225,12 +395,8 @@
   }
 
   void SetCursor(const Cursor& cursor, LocalFrame* local_root) override {
-    if (overlay_->inspect_mode_.Get() ==
-        protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
-      return;
-    }
     client_->SetCursorOverridden(false);
-    client_->SetCursor(cursor, overlay_->frame_impl_->GetFrame());
+    client_->SetCursor(cursor, overlay_->GetFrame());
     client_->SetCursorOverridden(true);
   }
 
@@ -238,7 +404,7 @@
                   const String& tooltip,
                   TextDirection direction) override {
     DCHECK_EQ(&frame, overlay_->OverlayMainFrame());
-    client_->SetToolTip(*overlay_->frame_impl_->GetFrame(), tooltip, direction);
+    client_->SetToolTip(*overlay_->GetFrame(), tooltip, direction);
   }
 
   void InvalidateRect(const IntRect&) override { overlay_->Invalidate(); }
@@ -295,7 +461,7 @@
   visitor->Trace(overlay_chrome_client_);
   visitor->Trace(overlay_host_);
   visitor->Trace(dom_agent_);
-  visitor->Trace(hovered_node_for_inspect_mode_);
+  visitor->Trace(inspect_tool_);
   InspectorBaseAgent::Trace(visitor);
 }
 
@@ -307,20 +473,8 @@
   setShowScrollBottleneckRects(show_scroll_bottleneck_rects_.Get());
   setShowHitTestBorders(show_hit_test_borders_.Get());
   setShowViewportSizeOnResize(show_size_on_resize_.Get());
-  if (paused_in_debugger_message_.Get().IsNull())
-    setPausedInDebuggerMessage(paused_in_debugger_message_.Get());
   setSuspended(suspended_.Get());
-  if (inspect_mode_.Get() != protocol::Overlay::InspectModeEnum::None) {
-    std::unique_ptr<protocol::Value> value =
-        protocol::StringUtil::parseJSON(inspect_mode_protocol_config_.Get());
-    std::unique_ptr<protocol::Overlay::HighlightConfig> highlight_config;
-    protocol::ErrorSupport errors;
-    if (value) {
-      highlight_config =
-          protocol::Overlay::HighlightConfig::fromValue(value.get(), &errors);
-    }
-    SetSearchingForNode(inspect_mode_.Get(), std::move(highlight_config));
-  }
+  PickTheRightTool();
 }
 
 void InspectorOverlayAgent::Dispose() {
@@ -351,10 +505,11 @@
   setShowScrollBottleneckRects(false);
   setShowHitTestBorders(false);
   setShowViewportSizeOnResize(false);
-  setPausedInDebuggerMessage(String());
   setSuspended(false);
-  SetSearchingForNode(protocol::Overlay::InspectModeEnum::None,
-                      Maybe<protocol::Overlay::HighlightConfig>());
+  paused_in_debugger_message_.Clear();
+  inspect_mode_.Set(protocol::Overlay::InspectModeEnum::None);
+  inspect_mode_protocol_config_.Set(String());
+  PickTheRightTool();
   SetNeedsUnbufferedInput(false);
   return Response::OK();
 }
@@ -455,7 +610,7 @@
 Response InspectorOverlayAgent::setPausedInDebuggerMessage(
     Maybe<String> message) {
   paused_in_debugger_message_.Set(message.fromMaybe(String()));
-  ScheduleUpdate();
+  PickTheRightTool();
   return Response::OK();
 }
 
@@ -467,19 +622,6 @@
   return Response::OK();
 }
 
-Response InspectorOverlayAgent::setInspectMode(
-    const String& mode,
-    Maybe<protocol::Overlay::HighlightConfig> highlight_config) {
-  if (mode != protocol::Overlay::InspectModeEnum::SearchForNode &&
-      mode != protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM &&
-      mode != protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot &&
-      mode != protocol::Overlay::InspectModeEnum::None) {
-    return Response::Error(
-        String("Unknown mode \"" + mode + "\" was provided."));
-  }
-  return SetSearchingForNode(mode, std::move(highlight_config));
-}
-
 Response InspectorOverlayAgent::highlightRect(
     int x,
     int y,
@@ -553,6 +695,7 @@
 
 Response InspectorOverlayAgent::hideHighlight() {
   InnerHideHighlight();
+  ScheduleUpdate();
   return Response::OK();
 }
 
@@ -575,8 +718,7 @@
 
   if (!frame_overlay_) {
     frame_overlay_ = FrameOverlay::Create(
-        frame_impl_->GetFrame(),
-        std::make_unique<InspectorPageOverlayDelegate>(*this));
+        GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
   }
 
   frame_overlay_->Update();
@@ -620,17 +762,22 @@
   return layer == frame_overlay_->GetGraphicsLayer()->CcLayer();
 }
 
+LocalFrame* InspectorOverlayAgent::GetFrame() const {
+  return frame_impl_->GetFrame();
+}
+
 void InspectorOverlayAgent::DispatchBufferedTouchEvents() {
   if (IsEmpty())
     return;
   OverlayMainFrame()->GetEventHandler().DispatchBufferedTouchEvents();
 }
 
-bool InspectorOverlayAgent::HandleInputEvent(const WebInputEvent& input_event) {
+WebInputEventResult InspectorOverlayAgent::HandleInputEvent(
+    const WebInputEvent& input_event) {
   if (input_event.GetType() == WebInputEvent::kMouseUp &&
       swallow_next_mouse_up_) {
     swallow_next_mouse_up_ = false;
-    return true;
+    return WebInputEventResult::kHandledSuppressed;
   }
 
   if (input_event.GetType() == WebInputEvent::kKeyUp &&
@@ -638,44 +785,24 @@
     auto keyboard_event = static_cast<const WebKeyboardEvent&>(input_event);
     if (keyboard_event.windows_key_code == VKEY_ESCAPE) {
       swallow_next_escape_up_ = false;
-      return true;
+      return WebInputEventResult::kHandledSuppressed;
     }
   }
 
-  if (IsEmpty())
-    return false;
-
-  // In the inspect mode, after clicking, keyboard events are dispatched here.
-  // Handle Escape below.
-
-  if (inspect_mode_.Get() != protocol::Overlay::InspectModeEnum::None &&
-      input_event.GetType() == WebInputEvent::kRawKeyDown) {
-    auto keyboard_event = static_cast<const WebKeyboardEvent&>(input_event);
-    if (keyboard_event.windows_key_code == VKEY_ESCAPE) {
-      // If we are in the process of dragging, reset the dragging.
-      // Otherwise, cancel searching.
-      if (screenshot_anchor_ != IntPoint::Zero()) {
-        screenshot_anchor_ = IntPoint::Zero();
-        ScheduleUpdate();
-      } else {
-        GetFrontend()->inspectModeCanceled();
-      }
-      swallow_next_escape_up_ = true;
-      return true;
-    }
-  }
-
-  bool handled = false;
+  if (IsEmpty() || !inspect_tool_)
+    return WebInputEventResult::kNotHandled;
 
   if (input_event.GetType() == WebInputEvent::kGestureTap) {
     // We only have a use for gesture tap.
     WebGestureEvent transformed_event = TransformWebGestureEvent(
         frame_impl_->GetFrameView(),
         static_cast<const WebGestureEvent&>(input_event));
-    handled = HandleGestureEvent(transformed_event);
-    if (handled)
-      return true;
-    OverlayMainFrame()->GetEventHandler().HandleGestureEvent(transformed_event);
+    if (inspect_tool_->HandleGestureTapEvent(transformed_event)) {
+      ScheduleUpdate();
+      return WebInputEventResult::kHandledSuppressed;
+    }
+    return OverlayMainFrame()->GetEventHandler().HandleGestureEvent(
+        transformed_event);
   }
 
   if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
@@ -683,34 +810,36 @@
         TransformWebMouseEvent(frame_impl_->GetFrameView(),
                                static_cast<const WebMouseEvent&>(input_event));
 
-    if (mouse_event.GetType() == WebInputEvent::kMouseMove)
-      handled = HandleMouseMove(mouse_event);
-    else if (mouse_event.GetType() == WebInputEvent::kMouseDown)
-      handled = HandleMouseDown(mouse_event);
-    else if (mouse_event.GetType() == WebInputEvent::kMouseUp)
-      handled = HandleMouseUp(mouse_event);
+    bool handled = false;
+    if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
+      handled = inspect_tool_->HandleMouseMove(mouse_event);
+    } else if (mouse_event.GetType() == WebInputEvent::kMouseDown) {
+      handled =
+          inspect_tool_->HandleMouseDown(mouse_event, &swallow_next_mouse_up_);
+    } else if (mouse_event.GetType() == WebInputEvent::kMouseUp) {
+      handled = inspect_tool_->HandleMouseUp(mouse_event);
+    }
 
-    if (handled)
-      return true;
+    if (handled) {
+      ScheduleUpdate();
+      return WebInputEventResult::kHandledSuppressed;
+    }
 
     if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
-      handled =
-          OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
-              mouse_event,
-              TransformWebMouseEventVector(frame_impl_->GetFrameView(),
-                                           std::vector<const WebInputEvent*>()),
-              TransformWebMouseEventVector(
-                  frame_impl_->GetFrameView(),
-                  std::vector<const WebInputEvent*>())) !=
-          WebInputEventResult::kNotHandled;
+      return OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
+          mouse_event,
+          TransformWebMouseEventVector(frame_impl_->GetFrameView(),
+                                       std::vector<const WebInputEvent*>()),
+          TransformWebMouseEventVector(frame_impl_->GetFrameView(),
+                                       std::vector<const WebInputEvent*>()));
     }
     if (mouse_event.GetType() == WebInputEvent::kMouseDown) {
-      handled = OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
-                    mouse_event) != WebInputEventResult::kNotHandled;
+      return OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
+          mouse_event);
     }
     if (mouse_event.GetType() == WebInputEvent::kMouseUp) {
-      handled = OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
-                    mouse_event) != WebInputEventResult::kNotHandled;
+      return OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
+          mouse_event);
     }
   }
 
@@ -718,15 +847,35 @@
     WebPointerEvent transformed_event = TransformWebPointerEvent(
         frame_impl_->GetFrameView(),
         static_cast<const WebPointerEvent&>(input_event));
-    handled = HandlePointerEvent(transformed_event);
-    if (handled)
-      return true;
-    OverlayMainFrame()->GetEventHandler().HandlePointerEvent(
+    bool handled = inspect_tool_->HandlePointerEvent(transformed_event);
+    if (handled) {
+      ScheduleUpdate();
+      return WebInputEventResult::kHandledSuppressed;
+    }
+    return OverlayMainFrame()->GetEventHandler().HandlePointerEvent(
         transformed_event, Vector<WebPointerEvent>(),
         Vector<WebPointerEvent>());
   }
+
   if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
-    OverlayMainFrame()->GetEventHandler().KeyEvent(
+    bool handled = inspect_tool_->HandleKeyboardEvent(
+        static_cast<const WebKeyboardEvent&>(input_event),
+        &swallow_next_escape_up_);
+    if (handled) {
+      ScheduleUpdate();
+      return WebInputEventResult::kHandledSuppressed;
+    }
+
+    // Exit tool upon unhandled Esc.
+    if (input_event.GetType() == WebInputEvent::kRawKeyDown) {
+      auto keyboard_event = static_cast<const WebKeyboardEvent&>(input_event);
+      if (keyboard_event.windows_key_code == VKEY_ESCAPE) {
+        GetFrontend()->inspectModeCanceled();
+        swallow_next_escape_up_ = true;
+        return WebInputEventResult::kHandledSuppressed;
+      }
+    }
+    return OverlayMainFrame()->GetEventHandler().KeyEvent(
         static_cast<const WebKeyboardEvent&>(input_event));
   }
 
@@ -734,11 +883,11 @@
     WebMouseWheelEvent transformed_event = TransformWebMouseWheelEvent(
         frame_impl_->GetFrameView(),
         static_cast<const WebMouseWheelEvent&>(input_event));
-    handled = OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
-                  transformed_event) != WebInputEventResult::kNotHandled;
+    return OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
+        transformed_event);
   }
 
-  return handled;
+  return WebInputEventResult::kNotHandled;
 }
 
 void InspectorOverlayAgent::InnerHideHighlight() {
@@ -746,7 +895,6 @@
   event_target_node_.Clear();
   highlight_quad_.reset();
   highlight_node_contrast_ = InspectorHighlightContrastInfo();
-  ScheduleUpdate();
 }
 
 void InspectorOverlayAgent::InnerHighlightNode(
@@ -798,31 +946,29 @@
     return true;
   bool has_visible_elements =
       highlight_node_ || event_target_node_ || highlight_quad_ ||
-      (resize_timer_active_ && show_size_on_resize_.Get()) ||
-      !paused_in_debugger_message_.Get().IsNull();
-  return !has_visible_elements &&
-         inspect_mode_.Get() == protocol::Overlay::InspectModeEnum::None;
+      (resize_timer_active_ && show_size_on_resize_.Get());
+  return !has_visible_elements && !inspect_tool_;
 }
 
 void InspectorOverlayAgent::ScheduleUpdate() {
-  auto& client = frame_impl_->GetFrame()->GetPage()->GetChromeClient();
+  auto& client = GetFrame()->GetPage()->GetChromeClient();
   if (IsEmpty()) {
     if (frame_overlay_) {
       frame_overlay_.reset();
       client.SetCursorOverridden(false);
-      client.SetCursor(PointerCursor(), frame_impl_->GetFrame());
+      client.SetCursor(PointerCursor(), GetFrame());
       if (auto* frame_view = frame_impl_->GetFrameView())
         frame_view->SetPaintArtifactCompositorNeedsUpdate();
     }
     return;
   }
   needs_update_ = true;
-  client.ScheduleAnimation(frame_impl_->GetFrame()->View());
+  client.ScheduleAnimation(GetFrame()->View());
 }
 
 void InspectorOverlayAgent::RebuildOverlayPage() {
   LocalFrameView* view = frame_impl_->GetFrameView();
-  LocalFrame* frame = frame_impl_->GetFrame();
+  LocalFrame* frame = GetFrame();
   if (!view || !frame)
     return;
 
@@ -835,9 +981,9 @@
   DrawMatchingSelector();
   DrawNodeHighlight();
   DrawQuadHighlight();
-  DrawPausedInDebuggerMessage();
   DrawViewSize();
-  DrawScreenshotBorder();
+  if (inspect_tool_)
+    inspect_tool_->Draw(1.f / WindowToViewportScale());
 }
 
 static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
@@ -902,40 +1048,13 @@
   EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue());
 }
 
-void InspectorOverlayAgent::DrawPausedInDebuggerMessage() {
-  if (inspect_mode_.Get() == protocol::Overlay::InspectModeEnum::None &&
-      !paused_in_debugger_message_.Get().IsNull()) {
-    EvaluateInOverlay("drawPausedInDebuggerMessage",
-                      paused_in_debugger_message_.Get());
-  }
-}
-
 void InspectorOverlayAgent::DrawViewSize() {
   if (resize_timer_active_ && show_size_on_resize_.Get())
     EvaluateInOverlay("drawViewSize", "");
 }
 
-void InspectorOverlayAgent::DrawScreenshotBorder() {
-  if (screenshot_anchor_ == IntPoint::Zero())
-    return;
-  const VisualViewport& visual_viewport =
-      frame_impl_->GetFrame()->GetPage()->GetVisualViewport();
-  IntPoint p1 = visual_viewport.RootFrameToViewport(screenshot_anchor_);
-  IntPoint p2 = visual_viewport.RootFrameToViewport(screenshot_position_);
-  float scale = 1.f / WindowToViewportScale();
-  p1.Scale(scale, scale);
-  p2.Scale(scale, scale);
-  std::unique_ptr<protocol::DictionaryValue> data =
-      protocol::DictionaryValue::create();
-  data->setInteger("x1", p1.X());
-  data->setInteger("y1", p1.Y());
-  data->setInteger("x2", p2.X());
-  data->setInteger("y2", p2.Y());
-  EvaluateInOverlay("drawScreenshotBorder", std::move(data));
-}
-
 float InspectorOverlayAgent::WindowToViewportScale() const {
-  LocalFrame* frame = frame_impl_->GetFrame();
+  LocalFrame* frame = GetFrame();
   if (!frame)
     return 1.0f;
   return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f);
@@ -953,12 +1072,12 @@
   FillWithEmptyClients(page_clients);
   DCHECK(!overlay_chrome_client_);
   overlay_chrome_client_ = InspectorOverlayChromeClient::Create(
-      frame_impl_->GetFrame()->GetPage()->GetChromeClient(), *this);
+      GetFrame()->GetPage()->GetChromeClient(), *this);
   page_clients.chrome_client = overlay_chrome_client_.Get();
   overlay_page_ = Page::Create(page_clients);
   overlay_host_ = MakeGarbageCollected<InspectorOverlayHost>(this);
 
-  Settings& settings = frame_impl_->GetFrame()->GetPage()->GetSettings();
+  Settings& settings = GetFrame()->GetPage()->GetSettings();
   Settings& overlay_settings = overlay_page_->GetSettings();
 
   overlay_settings.GetGenericFontFamilySettings().UpdateStandard(
@@ -1022,24 +1141,21 @@
 void InspectorOverlayAgent::Reset(const IntSize& viewport_size) {
   std::unique_ptr<protocol::DictionaryValue> reset_data =
       protocol::DictionaryValue::create();
-  reset_data->setDouble(
-      "deviceScaleFactor",
-      frame_impl_->GetFrame()->GetPage()->DeviceScaleFactorDeprecated());
-  reset_data->setDouble(
-      "pageScaleFactor",
-      frame_impl_->GetFrame()->GetPage()->GetVisualViewport().Scale());
+  reset_data->setDouble("deviceScaleFactor",
+                        GetFrame()->GetPage()->DeviceScaleFactorDeprecated());
+  reset_data->setDouble("pageScaleFactor",
+                        GetFrame()->GetPage()->GetVisualViewport().Scale());
 
   IntRect viewport_in_screen =
-      frame_impl_->GetFrame()->GetPage()->GetChromeClient().ViewportToScreen(
-          IntRect(IntPoint(), viewport_size), frame_impl_->GetFrame()->View());
+      GetFrame()->GetPage()->GetChromeClient().ViewportToScreen(
+          IntRect(IntPoint(), viewport_size), GetFrame()->View());
   reset_data->setObject("viewportSize",
                         BuildObjectForSize(viewport_in_screen.Size()));
 
   // The zoom factor in the overlay frame already has been multiplied by the
   // window to viewport scale (aka device scale factor), so cancel it.
-  reset_data->setDouble(
-      "pageZoomFactor",
-      frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale());
+  reset_data->setDouble("pageZoomFactor",
+                        GetFrame()->PageZoomFactor() / WindowToViewportScale());
 
   // TODO(szager): These values have been zero since root layer scrolling
   // landed. Probably they should be derived from
@@ -1111,7 +1227,7 @@
   inspect_mode_protocol_config_.Set(String());
   timer_.Stop();
   frame_overlay_.reset();
-  InnerHideHighlight();
+  PickTheRightTool();
 }
 
 void InspectorOverlayAgent::OverlayResumed() {
@@ -1132,26 +1248,15 @@
   ScheduleUpdate();
 }
 
-bool InspectorOverlayAgent::HandleMouseMove(const WebMouseEvent& event) {
-  if (!InSomeInspectMode())
-    return false;
-
-  if (inspect_mode_.Get() ==
-      protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
-    screenshot_position_ = RoundedIntPoint(event.PositionInRootFrame());
-    ScheduleUpdate();
-    return true;
-  }
-
-  LocalFrame* frame = frame_impl_->GetFrame();
+bool SearchingForNodeTool::HandleMouseMove(const WebMouseEvent& event) {
+  LocalFrame* frame = overlay_->GetFrame();
   if (!frame || !frame->View() || !frame->ContentLayoutObject())
     return false;
   Node* node = HoveredNodeForEvent(
       frame, event, event.GetModifiers() & WebInputEvent::kShiftKey);
 
   // Do not highlight within user agent shadow root unless requested.
-  if (inspect_mode_.Get() !=
-      protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM) {
+  if (!ua_shadow_) {
     ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node);
     if (shadow_root)
       node = &shadow_root->host();
@@ -1167,7 +1272,7 @@
   if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
     if (!IsA<LocalFrame>(frame_owner->ContentFrame())) {
       // Do not consume event so that remote frame can handle it.
-      InnerHideHighlight();
+      overlay_->hideHighlight();
       hovered_node_for_inspect_mode_.Clear();
       return false;
     }
@@ -1184,46 +1289,30 @@
     NodeHighlightRequested(node);
     bool omit_tooltip = event.GetModifiers() &
                         (WebInputEvent::kControlKey | WebInputEvent::kMetaKey);
-    InnerHighlightNode(node, event_target, String(),
-                       *inspect_mode_highlight_config_, omit_tooltip);
+    overlay_->InnerHighlightNode(node, event_target, String(),
+                                 *inspect_mode_highlight_config_, omit_tooltip);
   }
   return true;
 }
 
-bool InspectorOverlayAgent::HandleMouseDown(const WebMouseEvent& event) {
-  swallow_next_mouse_up_ = false;
-  if (!InSomeInspectMode())
-    return false;
-
-  if (inspect_mode_.Get() ==
-      protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
-    screenshot_anchor_ = RoundedIntPoint(event.PositionInRootFrame());
-    screenshot_position_ = screenshot_anchor_;
-    ScheduleUpdate();
-    return true;
-  }
-
+bool SearchingForNodeTool::HandleMouseDown(const WebMouseEvent& event,
+                                           bool* swallow_next_mouse_up) {
   if (hovered_node_for_inspect_mode_) {
-    swallow_next_mouse_up_ = true;
-    Inspect(hovered_node_for_inspect_mode_.Get());
+    *swallow_next_mouse_up = true;
+    overlay_->Inspect(hovered_node_for_inspect_mode_.Get());
     hovered_node_for_inspect_mode_.Clear();
     return true;
   }
   return false;
 }
 
-bool InspectorOverlayAgent::HandleMouseUp(const WebMouseEvent& event) {
-  if (inspect_mode_.Get() !=
-      protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
-    return false;
-  }
-
+bool ScreenshotTool::HandleMouseUp(const WebMouseEvent& event) {
   if (screenshot_anchor_ == IntPoint::Zero())
     return true;
   float scale = 1.0f;
   IntPoint p1 = screenshot_anchor_;
   IntPoint p2 = screenshot_position_;
-  if (LocalFrame* frame = frame_impl_->GetFrame()) {
+  if (LocalFrame* frame = overlay_->GetFrame()) {
     scale = frame->GetPage()->PageScaleFactor();
     p1 = frame->View()->ConvertFromRootFrame(p1);
     p2 = frame->View()->ConvertFromRootFrame(p2);
@@ -1235,9 +1324,9 @@
       p2 += scroll_offset;
     }
   }
-  float dp_to_dip = 1.f / WindowToViewportScale();
-  p1.Scale(dp_to_dip, dp_to_dip);
-  p2.Scale(dp_to_dip, dp_to_dip);
+  float dp_to_dip = 1.f / overlay_->WindowToViewportScale();
+  p1.Scale(scale, dp_to_dip);
+  p2.Scale(scale, dp_to_dip);
   // Points are in device independent pixels (dip) now.
   IntRect rect =
       UnionRectEvenIfEmpty(IntRect(p1, IntSize()), IntRect(p2, IntSize()));
@@ -1245,37 +1334,33 @@
     screenshot_anchor_ = IntPoint::Zero();
     return true;
   }
-  GetFrontend()->screenshotRequested(protocol::Page::Viewport::create()
-                                         .setX(rect.X())
-                                         .setY(rect.Y())
-                                         .setWidth(rect.Width())
-                                         .setHeight(rect.Height())
-                                         .setScale(scale)
-                                         .build());
+  frontend_->screenshotRequested(protocol::Page::Viewport::create()
+                                     .setX(rect.X())
+                                     .setY(rect.Y())
+                                     .setWidth(rect.Width())
+                                     .setHeight(rect.Height())
+                                     .setScale(scale)
+                                     .build());
   return true;
 }
 
-bool InspectorOverlayAgent::HandleGestureEvent(const WebGestureEvent& event) {
-  if (!InSomeInspectMode() || event.GetType() != WebInputEvent::kGestureTap)
-    return false;
-  Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
+bool SearchingForNodeTool::HandleGestureTapEvent(const WebGestureEvent& event) {
+  Node* node = HoveredNodeForEvent(overlay_->GetFrame(), event, false);
   if (node && inspect_mode_highlight_config_) {
-    InnerHighlightNode(node, nullptr, String(), *inspect_mode_highlight_config_,
-                       false);
-    Inspect(node);
+    overlay_->InnerHighlightNode(node, nullptr, String(),
+                                 *inspect_mode_highlight_config_, false);
+    overlay_->Inspect(node);
     return true;
   }
   return false;
 }
 
-bool InspectorOverlayAgent::HandlePointerEvent(const WebPointerEvent& event) {
-  if (!InSomeInspectMode())
-    return false;
-  Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
+bool SearchingForNodeTool::HandlePointerEvent(const WebPointerEvent& event) {
+  Node* node = HoveredNodeForEvent(overlay_->GetFrame(), event, false);
   if (node && inspect_mode_highlight_config_) {
-    InnerHighlightNode(node, nullptr, String(), *inspect_mode_highlight_config_,
-                       false);
-    Inspect(node);
+    overlay_->InnerHighlightNode(node, nullptr, String(),
+                                 *inspect_mode_highlight_config_, false);
+    overlay_->Inspect(node);
     return true;
   }
   return false;
@@ -1315,10 +1400,7 @@
   GetFrontend()->inspectNodeRequested(IdentifiersFactory::IntIdForNode(node));
 }
 
-void InspectorOverlayAgent::NodeHighlightRequested(Node* node) {
-  if (!enabled_.Get())
-    return;
-
+void SearchingForNodeTool::NodeHighlightRequested(Node* node) {
   while (node && !node->IsElementNode() && !node->IsDocumentNode() &&
          !node->IsDocumentFragment())
     node = node->ParentOrShadowHostNode();
@@ -1328,19 +1410,18 @@
 
   int node_id = dom_agent_->PushNodePathToFrontend(node);
   if (node_id)
-    GetFrontend()->nodeHighlightRequested(node_id);
+    frontend_->nodeHighlightRequested(node_id);
 }
 
-Response InspectorOverlayAgent::SetSearchingForNode(
-    String search_mode,
+Response InspectorOverlayAgent::setInspectMode(
+    const String& mode,
     Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object) {
-  if (search_mode == protocol::Overlay::InspectModeEnum::None) {
-    inspect_mode_.Set(search_mode);
-    hovered_node_for_inspect_mode_.Clear();
-    screenshot_anchor_ = IntPoint::Zero();
-    screenshot_position_ = IntPoint::Zero();
-    InnerHideHighlight();
-    return Response::OK();
+  if (mode != protocol::Overlay::InspectModeEnum::None &&
+      mode != protocol::Overlay::InspectModeEnum::SearchForNode &&
+      mode != protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM &&
+      mode != protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
+    return Response::Error(
+        String("Unknown mode \"" + mode + "\" was provided."));
   }
 
   String serialized_config =
@@ -1352,24 +1433,43 @@
       std::move(highlight_inspector_object), &config);
   if (!response.isSuccess())
     return response;
-  inspect_mode_.Set(search_mode);
+  inspect_mode_.Set(mode);
   inspect_mode_protocol_config_.Set(serialized_config);
-  inspect_mode_highlight_config_ = std::move(config);
 
-  if (search_mode ==
-      protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
-    auto& client = frame_impl_->GetFrame()->GetPage()->GetChromeClient();
-    client.SetCursorOverridden(false);
-    client.SetCursor(CrossCursor(), frame_impl_->GetFrame());
-    client.SetCursorOverridden(true);
-    hovered_node_for_inspect_mode_.Clear();
-    InnerHideHighlight();
-  } else {
-    ScheduleUpdate();
-  }
+  PickTheRightTool();
   return Response::OK();
 }
 
+void InspectorOverlayAgent::PickTheRightTool() {
+  InspectTool* inspect_tool = nullptr;
+
+  String inspect_mode = inspect_mode_.Get();
+  if (inspect_mode == protocol::Overlay::InspectModeEnum::SearchForNode ||
+      inspect_mode ==
+          protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM) {
+    inspect_tool = MakeGarbageCollected<SearchingForNodeTool>(
+        dom_agent_,
+        inspect_mode ==
+            protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM,
+        inspect_mode_protocol_config_.Get());
+  } else if (inspect_mode ==
+             protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
+    inspect_tool = MakeGarbageCollected<ScreenshotTool>();
+  } else if (!paused_in_debugger_message_.Get().IsNull()) {
+    inspect_tool = MakeGarbageCollected<PausedInDebuggerTool>(
+        paused_in_debugger_message_.Get());
+  }
+
+  // Setting inspect tool clears existing highlight.
+  InnerHideHighlight();
+  if (inspect_tool_)
+    inspect_tool_->Dispose();
+  inspect_tool_ = inspect_tool;
+  if (inspect_tool_)
+    inspect_tool_->Init(this, GetFrontend());
+  ScheduleUpdate();
+}
+
 Response InspectorOverlayAgent::HighlightConfigFromInspectorObject(
     Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object,
     std::unique_ptr<InspectorHighlightConfig>* out_config) {
@@ -1408,7 +1508,7 @@
 }
 
 void InspectorOverlayAgent::SetNeedsUnbufferedInput(bool unbuffered) {
-  LocalFrame* frame = frame_impl_->GetFrame();
+  LocalFrame* frame = GetFrame();
   if (frame) {
     frame->GetPage()->GetChromeClient().SetNeedsUnbufferedInputForDebugger(
         frame, unbuffered);
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
index d02a6d4c..5e3b6b1 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
@@ -34,6 +34,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/platform/web_input_event_result.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
 #include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
@@ -62,10 +63,37 @@
 class Page;
 class FrameOverlay;
 class WebGestureEvent;
+class WebKeyboardEvent;
 class WebMouseEvent;
 class WebLocalFrameImpl;
 class WebPointerEvent;
 
+class InspectorOverlayAgent;
+
+using OverlayFrontend = protocol::Overlay::Metainfo::FrontendClass;
+
+class CORE_EXPORT InspectTool : public GarbageCollectedFinalized<InspectTool> {
+ public:
+  virtual ~InspectTool() = default;
+  void Init(InspectorOverlayAgent* overlay, OverlayFrontend* frontend);
+  virtual bool HandleMouseDown(const WebMouseEvent&,
+                               bool* swallow_next_mouse_up);
+  virtual bool HandleMouseUp(const WebMouseEvent&);
+  virtual bool HandleMouseMove(const WebMouseEvent&);
+  virtual bool HandleGestureTapEvent(const WebGestureEvent&);
+  virtual bool HandlePointerEvent(const WebPointerEvent&);
+  virtual bool HandleKeyboardEvent(const WebKeyboardEvent&,
+                                   bool* swallow_next_escape_up);
+  virtual void Draw(float scale) {}
+  virtual void Trace(blink::Visitor* visitor);
+  virtual void Dispose() {}
+
+ protected:
+  virtual void DoInit() {}
+  Member<InspectorOverlayAgent> overlay_;
+  OverlayFrontend* frontend_ = nullptr;
+};
+
 class CORE_EXPORT InspectorOverlayAgent final
     : public InspectorBaseAgent<protocol::Overlay::Metainfo>,
       public InspectorOverlayHost::Listener {
@@ -127,8 +155,11 @@
 
   void Inspect(Node*);
   void DispatchBufferedTouchEvents();
-  bool HandleInputEvent(const WebInputEvent&);
+  WebInputEventResult HandleInputEvent(const WebInputEvent&);
   void PageLayoutInvalidated(bool resized);
+  void EvaluateInOverlay(const String& method, const String& argument);
+  void EvaluateInOverlay(const String& method,
+                         std::unique_ptr<protocol::Value> argument);
   String EvaluateInOverlayForTest(const String&);
 
   // Update the complete lifecycle (e.g., layout, paint) for the overlay.
@@ -138,6 +169,18 @@
 
   bool IsInspectorLayer(const cc::Layer*) const;
 
+  LocalFrame* GetFrame() const;
+  float WindowToViewportScale() const;
+  void InnerHighlightNode(Node*,
+                          Node* event_target,
+                          String selector,
+                          const InspectorHighlightConfig&,
+                          bool omit_tooltip);
+  protocol::Response HighlightConfigFromInspectorObject(
+      protocol::Maybe<protocol::Overlay::HighlightConfig>
+          highlight_inspector_object,
+      std::unique_ptr<InspectorHighlightConfig>*);
+
  private:
   class InspectorOverlayChromeClient;
   class InspectorPageOverlayDelegate;
@@ -150,52 +193,28 @@
   void DrawMatchingSelector();
   void DrawNodeHighlight();
   void DrawQuadHighlight();
-  void DrawPausedInDebuggerMessage();
   void DrawViewSize();
-  void DrawScreenshotBorder();
 
-  float WindowToViewportScale() const;
 
   Page* OverlayPage();
   LocalFrame* OverlayMainFrame();
   void Reset(const IntSize& viewport_size);
-  void EvaluateInOverlay(const String& method, const String& argument);
-  void EvaluateInOverlay(const String& method,
-                         std::unique_ptr<protocol::Value> argument);
   void OnTimer(TimerBase*);
   void RebuildOverlayPage();
   void Invalidate();
   void ScheduleUpdate();
   void ClearInternal();
 
-  bool HandleMouseDown(const WebMouseEvent&);
-  bool HandleMouseUp(const WebMouseEvent&);
-  bool HandleGestureEvent(const WebGestureEvent&);
-  bool HandlePointerEvent(const WebPointerEvent&);
-  bool HandleMouseMove(const WebMouseEvent&);
-
   protocol::Response CompositingEnabled();
 
   bool InSomeInspectMode();
-  void NodeHighlightRequested(Node*);
-  protocol::Response SetSearchingForNode(
-      String search_mode,
-      protocol::Maybe<protocol::Overlay::HighlightConfig>);
-  protocol::Response HighlightConfigFromInspectorObject(
-      protocol::Maybe<protocol::Overlay::HighlightConfig>
-          highlight_inspector_object,
-      std::unique_ptr<InspectorHighlightConfig>*);
   void InnerHighlightQuad(std::unique_ptr<FloatQuad>,
                           protocol::Maybe<protocol::DOM::RGBA> color,
                           protocol::Maybe<protocol::DOM::RGBA> outline_color);
-  void InnerHighlightNode(Node*,
-                          Node* event_target,
-                          String selector,
-                          const InspectorHighlightConfig&,
-                          bool omit_tooltip);
   void InnerHideHighlight();
 
   void SetNeedsUnbufferedInput(bool unbuffered);
+  void PickTheRightTool();
 
   Member<WebLocalFrameImpl> frame_impl_;
   Member<InspectedFrames> inspected_frames_;
@@ -219,13 +238,10 @@
   v8_inspector::V8InspectorSession* v8_session_;
   Member<InspectorDOMAgent> dom_agent_;
   std::unique_ptr<FrameOverlay> frame_overlay_;
-  Member<Node> hovered_node_for_inspect_mode_;
+  Member<InspectTool> inspect_tool_;
   bool swallow_next_mouse_up_;
   bool swallow_next_escape_up_;
-  std::unique_ptr<InspectorHighlightConfig> inspect_mode_highlight_config_;
   DOMNodeId backend_node_id_to_inspect_;
-  IntPoint screenshot_anchor_;
-  IntPoint screenshot_position_;
   InspectorAgentState::Boolean enabled_;
   InspectorAgentState::Boolean suspended_;
   InspectorAgentState::Boolean show_ad_highlights_;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc
index 7590ce303..5f15caa 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc
@@ -194,6 +194,24 @@
          index != VisualLastCharacterOf(ContainingLineOf(index));
 }
 
+bool NGCaretNavigator::IsEnterableChildContext(unsigned index) const {
+  DCHECK_LT(index, GetText().length());
+  if (GetText()[index] != kObjectReplacementCharacter)
+    return false;
+
+  const NGInlineItem& item = GetData().FindItemForTextOffset(index);
+  if (item.Type() != NGInlineItem::kAtomicInline)
+    return false;
+  DCHECK(item.GetLayoutObject());
+  const LayoutObject* object = item.GetLayoutObject();
+  if (!object->IsLayoutBlockFlow())
+    return false;
+  if (!object->NonPseudoNode() || !object->GetNode()->IsElementNode())
+    return false;
+  const Element* node = ToElement(object->GetNode());
+  return !node->GetShadowRoot() || !node->GetShadowRoot()->IsUserAgent();
+}
+
 NGCaretNavigator::Position NGCaretNavigator::LeftEdgeOf(unsigned index) const {
   return EdgeOfInternal(index, MoveDirection::kTowardsLeft);
 }
@@ -354,9 +372,14 @@
     if (next.type != VisualMovementResultType::kWithinContext)
       return {next.type, base::nullopt};
 
-    if (next.has_passed_character)
+    if (next.has_passed_character) {
       has_passed_character = true;
 
+      const unsigned last_passed_character = next.position->index;
+      if (IsEnterableChildContext(last_passed_character))
+        return {VisualMovementResultType::kEnteredChildContext, runner};
+    }
+
     runner = *next.position;
     last_position = runner;
 
@@ -367,4 +390,40 @@
   return {VisualMovementResultType::kWithinContext, *last_position};
 }
 
+NGCaretNavigator::Position NGCaretNavigator::LeftmostPositionInFirstLine()
+    const {
+  Line first_line = ContainingLineOf(0);
+  unsigned leftmost_character =
+      VisualMostForwardCharacterOf(first_line, MoveDirection::kTowardsLeft);
+  // TODO(xiaochengh): Handle if the caret position is invalid.
+  return LeftEdgeOf(leftmost_character);
+}
+
+NGCaretNavigator::Position NGCaretNavigator::RightmostPositionInFirstLine()
+    const {
+  Line first_line = ContainingLineOf(0);
+  unsigned rightmost_character =
+      VisualMostForwardCharacterOf(first_line, MoveDirection::kTowardsRight);
+  // TODO(xiaochengh): Handle if the caret position is invalid.
+  return RightEdgeOf(rightmost_character);
+}
+
+NGCaretNavigator::Position NGCaretNavigator::LeftmostPositionInLastLine()
+    const {
+  Line last_line = ContainingLineOf(GetText().length() - 1);
+  unsigned leftmost_character =
+      VisualMostForwardCharacterOf(last_line, MoveDirection::kTowardsLeft);
+  // TODO(xiaochengh): Handle if the caret position is invalid.
+  return LeftEdgeOf(leftmost_character);
+}
+
+NGCaretNavigator::Position NGCaretNavigator::RightmostPositionInLastLine()
+    const {
+  Line last_line = ContainingLineOf(GetText().length() - 1);
+  unsigned rightmost_character =
+      VisualMostForwardCharacterOf(last_line, MoveDirection::kTowardsRight);
+  // TODO(xiaochengh): Handle if the caret position is invalid.
+  return RightEdgeOf(rightmost_character);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h
index f4e61d4..6c60d7f 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h
@@ -76,12 +76,12 @@
   // Left/right visual movements
   // TODO(xiaochengh): Handle the following
   // - Grapheme clusters
-  // - Enterable atomic inlines
 
   enum class VisualMovementResultType {
     kWithinContext,
     kBeforeContext,
-    kAfterContext
+    kAfterContext,
+    kEnteredChildContext
   };
 
   // Given the character at the logical |index|, returns the logical index of
@@ -105,6 +105,13 @@
 
   // Given a caret position, moves it left/right by one grapheme cluster and
   // returns the result.
+  // Note: If we end up entering an inline block, the result |Position| is
+  // either before or after the inline block, depending on from which side the
+  // inline block is entered. For example:
+  // RightPositionOf(abc|<inline-block>def</inline-block>ghi)
+  // -> {inline-block, PositionAnchorType::kBefore}
+  // LeftPositionOf(abc<inline-block>def</inline-block>|ghi)
+  // -> {inline-block, PositionAnchorType::kAfter}
   struct VisualCaretMovementResult {
     bool IsWithinContext() const {
       return type == VisualMovementResultType::kWithinContext;
@@ -115,6 +122,9 @@
     bool IsAfterContext() const {
       return type == VisualMovementResultType::kAfterContext;
     }
+    bool HasEnteredChildContext() const {
+      return type == VisualMovementResultType::kEnteredChildContext;
+    }
 
     VisualMovementResultType type;
     base::Optional<Position> position;
@@ -122,19 +132,30 @@
   VisualCaretMovementResult LeftPositionOf(const Position&) const;
   VisualCaretMovementResult RightPositionOf(const Position&) const;
 
+  // TODO(xiaochengh): Specify and implement the behavior in edge cases, e.g.,
+  // when the leftmost character of the first line is CSS-generated.
+  Position LeftmostPositionInFirstLine() const;
+  Position RightmostPositionInFirstLine() const;
+  Position LeftmostPositionInLastLine() const;
+  Position RightmostPositionInLastLine() const;
+
  private:
   // A caret position is invalid if it is:
   // - kAfter to a line break character.
   // - Anchored to a collapsible space that's removed by line wrap.
   // - Anchored to a character that's ignored in caret movement.
-  // TODO(xiaochengh): Handle the the following:
-  // - Enterable atomic inlines
   bool IsValidCaretPosition(const Position&) const;
   bool IsLineBreak(unsigned index) const;
   bool IsCollapsibleWhitespace(unsigned index) const;
   bool IsCollapsedSpaceByLineWrap(unsigned index) const;
   bool IsIgnoredInCaretMovement(unsigned index) const;
 
+  // Returns true if the character at |index| represents a child block
+  // formatting context that can be entered by caret navigation. Such contexts
+  // must be atomic inlines (inline block, inline table, ...) and must not host
+  // user agent shadow tree (which excludes, e.g., <input> and image alt text).
+  bool IsEnterableChildContext(unsigned index) const;
+
   enum class MoveDirection { kTowardsLeft, kTowardsRight };
   static MoveDirection OppositeDirectionOf(MoveDirection);
   static bool TowardsSameDirection(MoveDirection, TextDirection);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc
index 1192a8e..1beb7a4a 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc
@@ -420,4 +420,42 @@
   EXPECT_EQ(CaretAfter(9), *LeftPositionOf(CaretBefore(14)).position);
 }
 
+TEST_F(NGCaretNavigatorTest, EnterableInlineBlock) {
+  SetupHtml("container",
+            "<div id=container>foo"
+            "<span style='display:inline-block'>bar</span>"
+            "baz</div>");
+
+  // Moving right from "foo|" should enter the span from front.
+  EXPECT_TRUE(RightPositionOf(CaretAfter(2)).HasEnteredChildContext());
+  EXPECT_EQ(CaretBefore(3), *RightPositionOf(CaretAfter(2)).position);
+  EXPECT_TRUE(RightPositionOf(CaretBefore(3)).HasEnteredChildContext());
+  EXPECT_EQ(CaretBefore(3), *RightPositionOf(CaretBefore(3)).position);
+
+  // Moving left from "|baz" should enter the span from behind.
+  EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).HasEnteredChildContext());
+  EXPECT_EQ(CaretAfter(3), *LeftPositionOf(CaretBefore(4)).position);
+  EXPECT_TRUE(LeftPositionOf(CaretAfter(3)).HasEnteredChildContext());
+  EXPECT_EQ(CaretAfter(3), *LeftPositionOf(CaretAfter(3)).position);
+}
+
+TEST_F(NGCaretNavigatorTest, UnenterableInlineBlock) {
+  SetupHtml("container",
+            "<div id=container>foo"
+            "<input value=bar>"
+            "baz</div>");
+
+  // Moving right from "foo|" should reach "<input>|".
+  EXPECT_TRUE(RightPositionOf(CaretAfter(2)).IsWithinContext());
+  EXPECT_EQ(CaretAfter(3), *RightPositionOf(CaretAfter(2)).position);
+  EXPECT_TRUE(RightPositionOf(CaretBefore(3)).IsWithinContext());
+  EXPECT_EQ(CaretAfter(3), *RightPositionOf(CaretBefore(3)).position);
+
+  // Moving left from "|baz" should reach "|<input>".
+  EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).IsWithinContext());
+  EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretBefore(4)).position);
+  EXPECT_TRUE(LeftPositionOf(CaretAfter(3)).IsWithinContext());
+  EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretAfter(3)).position);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
index 86a5d56..6f90707 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -61,7 +61,7 @@
 }
 
 void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
-  const bool is_horizontal_flow = algorithm->IsHorizontalFlow();
+  const bool is_horizontal_flow = algorithm_->IsHorizontalFlow();
   for (NGLayoutInputNode generic_child = Node().FirstChild(); generic_child;
        generic_child = generic_child.NextSibling()) {
     NGBlockNode child = ToNGBlockNode(generic_child);
@@ -98,7 +98,7 @@
     // only ever use it if the child's inline axis is our main axis.
     MinMaxSizeInput input(
         /* percentage_resolution_block_size */ content_box_size_.block_size);
-    MinMaxSize min_max_sizes_border_box = child.ComputeMinMaxSize(
+    MinMaxSize intrinsic_sizes_border_box = child.ComputeMinMaxSize(
         child_style.GetWritingMode(), input, &child_space);
     // TODO(dgrogan): Don't layout every time, just when you need to.
     scoped_refptr<const NGLayoutResult> layout_result =
@@ -112,7 +112,7 @@
     const Length& flex_basis = child_style.FlexBasis();
     if (flex_basis.IsAuto() && length_in_main_axis.IsAuto()) {
       if (MainAxisIsInlineAxis(child))
-        flex_base_border_box = min_max_sizes_border_box.max_size;
+        flex_base_border_box = intrinsic_sizes_border_box.max_size;
       else
         flex_base_border_box = fragment_in_child_writing_mode.BlockSize();
     } else {
@@ -123,7 +123,7 @@
       if (MainAxisIsInlineAxis(child)) {
         flex_base_border_box = ResolveInlineLength(
             child_space, child_style, border_padding_in_child_writing_mode,
-            min_max_sizes_border_box, length_to_resolve,
+            intrinsic_sizes_border_box, length_to_resolve,
             LengthResolveType::kContentSize, LengthResolvePhase::kLayout);
       } else {
         // Flex container's main axis is in child's block direction. Child's
@@ -155,7 +155,7 @@
     if (MainAxisIsInlineAxis(child)) {
       min_max_sizes_in_main_axis_direction.max_size = ResolveInlineLength(
           child_space, child_style, border_padding_in_child_writing_mode,
-          min_max_sizes_border_box, max, LengthResolveType::kMaxSize,
+          intrinsic_sizes_border_box, max, LengthResolveType::kMaxSize,
           LengthResolvePhase::kLayout);
     } else {
       min_max_sizes_in_main_axis_direction.max_size = ResolveBlockLength(
@@ -167,7 +167,7 @@
     const Length& min = is_horizontal_flow ? child.Style().MinWidth()
                                            : child.Style().MinHeight();
     if (min.IsAuto()) {
-      if (algorithm->ShouldApplyMinSizeAutoForChild(*child.GetLayoutBox())) {
+      if (algorithm_->ShouldApplyMinSizeAutoForChild(*child.GetLayoutBox())) {
         // TODO(dgrogan): Port logic from
         // https://www.w3.org/TR/css-flexbox-1/#min-size-auto and
         // LayoutFlexibleBox::ComputeMinAndMaxSizesForChild
@@ -175,7 +175,7 @@
     } else if (MainAxisIsInlineAxis(child)) {
       min_max_sizes_in_main_axis_direction.min_size = ResolveInlineLength(
           child_space, child_style, border_padding_in_child_writing_mode,
-          min_max_sizes_border_box, min, LengthResolveType::kMinSize,
+          intrinsic_sizes_border_box, min, LengthResolveType::kMinSize,
           LengthResolvePhase::kLayout);
     } else {
       min_max_sizes_in_main_axis_direction.min_size = ResolveBlockLength(
@@ -184,7 +184,7 @@
           LengthResolveType::kMinSize, LengthResolvePhase::kLayout);
     }
 
-    algorithm
+    algorithm_
         ->emplace_back(child.GetLayoutBox(), flex_base_content_size,
                        min_max_sizes_in_main_axis_direction,
                        main_axis_border_and_padding, main_axis_margin)
@@ -199,8 +199,8 @@
       ShrinkAvailableSize(border_box_size_, border_scrollbar_padding_);
 
   const LayoutUnit line_break_length = MainAxisContentExtent(LayoutUnit::Max());
-  algorithm.emplace(&Style(), line_break_length);
-  const bool is_horizontal_flow = algorithm->IsHorizontalFlow();
+  algorithm_.emplace(&Style(), line_break_length);
+  const bool is_horizontal_flow = algorithm_->IsHorizontalFlow();
 
   ConstructAndAppendFlexItems();
 
@@ -213,7 +213,7 @@
   FlexLine* line;
   LayoutUnit max_main_axis_extent;
   while (
-      (line = algorithm->ComputeNextFlexLine(border_box_size_.inline_size))) {
+      (line = algorithm_->ComputeNextFlexLine(border_box_size_.inline_size))) {
     line->SetContainerMainInnerSize(
         MainAxisContentExtent(line->sum_hypothetical_main_size));
     line->FreezeInflexibleItems();
@@ -294,10 +294,10 @@
     final_content_cross_size =
         border_box_size_.inline_size - border_scrollbar_padding_.InlineSum();
   }
-  if (!algorithm->IsMultiline() && !algorithm->FlexLines().IsEmpty())
-    algorithm->FlexLines()[0].cross_axis_extent = final_content_cross_size;
+  if (!algorithm_->IsMultiline() && !algorithm_->FlexLines().IsEmpty())
+    algorithm_->FlexLines()[0].cross_axis_extent = final_content_cross_size;
 
-  for (FlexLine& line_context : algorithm->FlexLines()) {
+  for (FlexLine& line_context : algorithm_->FlexLines()) {
     for (wtf_size_t child_number = 0;
          child_number < line_context.line_items.size(); ++child_number) {
       FlexItem& flex_item = line_context.line_items[child_number];
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
index d94b2c4..a85d041 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
@@ -54,7 +54,7 @@
   NGLogicalSize content_box_size_;
   // This is populated at the top of Layout(), so isn't available in
   // ComputeMinMaxSize() or anything it calls.
-  base::Optional<FlexLayoutAlgorithm> algorithm;
+  base::Optional<FlexLayoutAlgorithm> algorithm_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 88189e1..f14ebf89 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -735,18 +735,37 @@
   if (!line_boxes.size())
     return;
 
-  // TODO(layout-dev): Early return if no line intersects cull rect.
+  const bool is_horizontal =
+      IsHorizontalWritingMode(box_fragment_.Style().GetWritingMode());
+
   for (const NGPaintFragment* line : line_boxes) {
-    if (line->PhysicalFragment().IsFloatingOrOutOfFlowPositioned())
+    const NGPhysicalFragment& child_fragment = line->PhysicalFragment();
+    if (child_fragment.IsFloatingOrOutOfFlowPositioned())
       continue;
+
+    // Check if CullRect intersects with this child, only in block direction
+    // because soft-wrap and <br> needs to paint outside of InkOverflow() in
+    // inline direction.
     const LayoutPoint child_offset =
         paint_offset + line->Offset().ToLayoutPoint();
-    if (line->PhysicalFragment().IsListMarker()) {
+    NGPhysicalOffsetRect child_rect = line->InkOverflow();
+    if (is_horizontal) {
+      LayoutUnit y = child_rect.offset.top + child_offset.Y();
+      if (!paint_info.GetCullRect().IntersectsVerticalRange(
+              y, y + child_rect.size.height))
+        continue;
+    } else {
+      LayoutUnit x = child_rect.offset.left + child_offset.X();
+      if (!paint_info.GetCullRect().IntersectsHorizontalRange(
+              x, x + child_rect.size.width))
+        continue;
+    }
+
+    if (child_fragment.IsListMarker()) {
       PaintAtomicInlineChild(*line, paint_info);
       continue;
     }
-    DCHECK(line->PhysicalFragment().IsLineBox())
-        << line->PhysicalFragment().ToString();
+    DCHECK(child_fragment.IsLineBox());
 
     if (paint_info.phase == PaintPhase::kForeground &&
         NGFragmentPainter::ShouldRecordHitTestData(paint_info,
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index efa8a76d..26ed9a0d 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -356,6 +356,7 @@
     "worklet/animation_and_paint_worklet_thread_test.cc",
     "worklet/worklet_thread_test_common.cc",
     "worklet/worklet_thread_test_common.h",
+    "xr/xr_rigid_transform_test.cc",
   ]
 
   configs += [
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.cc b/third_party/blink/renderer/modules/background_sync/sync_manager.cc
index 4551366..6fd0ba5 100644
--- a/third_party/blink/renderer/modules/background_sync/sync_manager.cc
+++ b/third_party/blink/renderer/modules/background_sync/sync_manager.cc
@@ -83,7 +83,8 @@
       // Let the service know that the registration promise is resolved so that
       // it can fire the event.
       GetBackgroundSyncServicePtr()->DidResolveRegistration(
-          registration_->RegistrationId(), options->tag);
+          registration_->RegistrationId(), options->tag,
+          mojom::blink::BackgroundSyncType::ONE_SHOT);
       break;
     case mojom::blink::BackgroundSyncError::NOT_FOUND:
       NOTREACHED();
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
index dff51d7..26cdc33 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
@@ -11,6 +11,7 @@
 
 #include "base/single_thread_task_runner.h"
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -65,7 +66,7 @@
     mojom::blink::IDBErrorPtr error,
     mojom::blink::IDBCursorValuePtr cursor_value) {
   if (error) {
-    callbacks->Error(error->error_code, error->error_message);
+    callbacks->Error(error->error_code, std::move(error->error_message));
     callbacks.reset();
     return;
   }
@@ -76,9 +77,18 @@
     return;
   }
 
-  callbacks->SuccessCursorContinue(std::move(cursor_value->key),
-                                   std::move(cursor_value->primary_key),
-                                   std::move(cursor_value->value));
+  if (cursor_value->keys.size() != 1u ||
+      cursor_value->primary_keys.size() != 1u ||
+      cursor_value->values.size() != 1u) {
+    callbacks->Error(blink::kWebIDBDatabaseExceptionUnknownError,
+                     "Invalid response");
+    callbacks.reset();
+    return;
+  }
+
+  callbacks->SuccessCursorContinue(std::move(cursor_value->keys[0]),
+                                   std::move(cursor_value->primary_keys[0]),
+                                   std::move(cursor_value->values[0]));
   callbacks.reset();
 }
 
@@ -105,7 +115,8 @@
 
       callbacks->SetState(weak_factory_.GetWeakPtr(), transaction_id_);
       cursor_->Prefetch(prefetch_amount_,
-                        GetCallbacksProxy(std::move(callbacks)));
+                        WTF::Bind(&WebIDBCursorImpl::PrefetchCallback,
+                                  WTF::Unretained(this), std::move(callbacks)));
 
       // Increase prefetch_amount_ exponentially.
       prefetch_amount_ *= 2;
@@ -133,7 +144,7 @@
     mojom::blink::IDBErrorPtr error,
     mojom::blink::IDBCursorValuePtr value) {
   if (error) {
-    callbacks->Error(error->error_code, error->error_message);
+    callbacks->Error(error->error_code, std::move(error->error_message));
     callbacks.reset();
     return;
   }
@@ -144,9 +155,47 @@
     return;
   }
 
-  callbacks->SuccessCursorContinue(std::move(value->key),
-                                   std::move(value->primary_key),
-                                   std::move(value->value));
+  if (value->keys.size() != 1u || value->primary_keys.size() != 1u ||
+      value->values.size() != 1u) {
+    callbacks->Error(blink::kWebIDBDatabaseExceptionUnknownError,
+                     "Invalid response");
+    callbacks.reset();
+    return;
+  }
+
+  callbacks->SuccessCursorContinue(std::move(value->keys[0]),
+                                   std::move(value->primary_keys[0]),
+                                   std::move(value->values[0]));
+  callbacks.reset();
+}
+
+void WebIDBCursorImpl::PrefetchCallback(
+    std::unique_ptr<WebIDBCallbacks> callbacks,
+    mojom::blink::IDBErrorPtr error,
+    mojom::blink::IDBCursorValuePtr value) {
+  if (error) {
+    callbacks->Error(error->error_code, std::move(error->error_message));
+    callbacks.reset();
+    return;
+  }
+
+  if (!value) {
+    callbacks->SuccessValue(nullptr);
+    callbacks.reset();
+    return;
+  }
+
+  if (value->keys.size() != value->primary_keys.size() ||
+      value->keys.size() != value->values.size()) {
+    callbacks->Error(blink::kWebIDBDatabaseExceptionUnknownError,
+                     "Invalid response");
+    callbacks.reset();
+    return;
+  }
+
+  callbacks->SuccessCursorPrefetch(std::move(value->keys),
+                                   std::move(value->primary_keys),
+                                   std::move(value->values));
   callbacks.reset();
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
index a5a8405..e37de34 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
@@ -33,6 +33,9 @@
   void CursorContinueCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
                               mojom::blink::IDBErrorPtr error,
                               mojom::blink::IDBCursorValuePtr value);
+  void PrefetchCallback(std::unique_ptr<WebIDBCallbacks> callbacks,
+                        mojom::blink::IDBErrorPtr error,
+                        mojom::blink::IDBCursorValuePtr value);
 
   void PostSuccessHandlerCallback() override;
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
index 15183d3..13599d7 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
@@ -31,11 +31,12 @@
         &MockCursorImpl::CursorDestroyed, base::Unretained(this)));
   }
 
-  void Prefetch(
-      int32_t count,
-      mojom::blink::IDBCallbacksAssociatedPtrInfo callbacks) override {
+  void Prefetch(int32_t count,
+                mojom::blink::IDBCursor::PrefetchCallback callback) override {
     ++prefetch_calls_;
     last_prefetch_count_ = count;
+    std::move(callback).Run(mojom::blink::IDBErrorPtr(),
+                            mojom::blink::IDBCursorValuePtr());
   }
 
   void PrefetchReset(int32_t used_prefetches,
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
index 40b9252..6fe738e 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -732,13 +732,11 @@
   // Remove the track.
   for (auto it = adapters_.begin(); it != adapters_.end(); ++it) {
     track_callbacks = (*it)->RemoveAndGetCallbacks(track);
-    if (track_callbacks.frame_callback.is_null())
-      continue;
     if ((*it)->IsEmpty()) {
       DCHECK(!track_callbacks.frame_callback.is_null());
       adapters_.erase(it);
+      break;
     }
-    break;
   }
 
   // If the track was found, re-add it with new settings.
diff --git a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
index 1035bdd..fb5f296e 100644
--- a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
+++ b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
@@ -334,11 +334,11 @@
   AssertGraphOwner();
 
   // Quick exit if there are no handlers that need to be deleted so that we
-  // don't unecessarily post a task.  Be onsistent with
+  // don't unecessarily post a task.  Be consistent with
   // |DeleteHandlersOnMainThread()| so we don't accidentally return early when
   // there are handlers that could be deleted.
   if (rendering_orphan_handlers_.IsEmpty() &&
-      finished_tail_processing_handlers_.size()) {
+      finished_tail_processing_handlers_.size() == 0) {
     return;
   }
 
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.cc b/third_party/blink/renderer/modules/webgpu/webgpu_device.cc
index 3d78a0c..111a129 100644
--- a/third_party/blink/renderer/modules/webgpu/webgpu_device.cc
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_device.cc
@@ -42,10 +42,6 @@
   return adapter_;
 }
 
-void WebGPUDevice::dummy() const {
-  Interface()->Dummy();
-}
-
 void WebGPUDevice::Trace(blink::Visitor* visitor) {
   visitor->Trace(adapter_);
   ScriptWrappable::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.h b/third_party/blink/renderer/modules/webgpu/webgpu_device.h
index 0275962..2d86aef 100644
--- a/third_party/blink/renderer/modules/webgpu/webgpu_device.h
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_device.h
@@ -24,8 +24,6 @@
 
   WebGPUAdapter* adapter() const;
 
-  void dummy() const;
-
   void Trace(blink::Visitor*) override;
 
  private:
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.idl b/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
index 793ffad9..47f1b690 100644
--- a/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
@@ -6,6 +6,4 @@
     RuntimeEnabled=WebGPU
 ] interface WebGPUDevice {
     readonly attribute WebGPUAdapter adapter;
-
-    void dummy();
 };
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc b/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
index 261c5500..c4e4b2eb 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
@@ -33,9 +33,13 @@
     position_ =
         DOMPointReadOnly::Create(decomposed.translate_x, decomposed.translate_y,
                                  decomposed.translate_z, 1.0);
+
+    // TODO(https://crbug.com/929841): Minuses are needed as a workaround for
+    // bug in TransformationMatrix so that callers can still pass non-inverted
+    // quaternions.
     orientation_ = makeNormalizedQuaternion(
-        decomposed.quaternion_x, decomposed.quaternion_y,
-        decomposed.quaternion_z, decomposed.quaternion_w);
+        -decomposed.quaternion_x, -decomposed.quaternion_y,
+        -decomposed.quaternion_z, decomposed.quaternion_w);
   } else {
     // TODO: Is this the correct way to handle a failure here?
     position_ = DOMPointReadOnly::Create(0.0, 0.0, 0.0, 1.0);
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.h b/third_party/blink/renderer/modules/xr/xr_rigid_transform.h
index aba47f7..13175de 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.h
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.h
@@ -11,12 +11,15 @@
 #include "third_party/blink/renderer/core/geometry/dom_point_init.h"
 #include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
 
 namespace blink {
 
-class XRRigidTransform : public ScriptWrappable {
+// MODULES_EXPORT is required for unit tests using XRRigidTransform (currently
+// just xr_rigid_transform_test.cc) to build without linker errors.
+class MODULES_EXPORT XRRigidTransform : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -29,6 +32,8 @@
   XRRigidTransform(DOMPointInit*, DOMPointInit*);
   static XRRigidTransform* Create(DOMPointInit*, DOMPointInit*);
 
+  ~XRRigidTransform() override = default;
+
   DOMPointReadOnly* position() const { return position_; }
   DOMPointReadOnly* orientation() const { return orientation_; }
   DOMFloat32Array* matrix();
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform_test.cc b/third_party/blink/renderer/modules/xr/xr_rigid_transform_test.cc
new file mode 100644
index 0000000..4a09aa9
--- /dev/null
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform_test.cc
@@ -0,0 +1,129 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/xr/xr_rigid_transform.h"
+
+#include <vector>
+
+#include "third_party/blink/renderer/modules/xr/xr_utils.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+namespace {
+
+constexpr double kEpsilon = 0.0001;
+
+static void AssertDOMPointsEqualForTest(const DOMPointReadOnly* a,
+                                        const DOMPointReadOnly* b) {
+  ASSERT_NEAR(a->x(), b->x(), kEpsilon);
+  ASSERT_NEAR(a->y(), b->y(), kEpsilon);
+  ASSERT_NEAR(a->z(), b->z(), kEpsilon);
+  ASSERT_NEAR(a->w(), b->w(), kEpsilon);
+}
+
+std::vector<double> GetMatrixDataForTest(const TransformationMatrix& matrix) {
+  std::vector<double> data{
+      matrix.M11(), matrix.M12(), matrix.M13(), matrix.M14(),
+      matrix.M21(), matrix.M22(), matrix.M23(), matrix.M24(),
+      matrix.M31(), matrix.M32(), matrix.M33(), matrix.M34(),
+      matrix.M41(), matrix.M42(), matrix.M43(), matrix.M44()};
+  return data;
+}
+
+static void AssertMatricesEqualForTest(const TransformationMatrix& a,
+                                       const TransformationMatrix& b) {
+  const std::vector<double> a_data = GetMatrixDataForTest(a);
+  const std::vector<double> b_data = GetMatrixDataForTest(b);
+  for (int i = 0; i < 16; ++i) {
+    ASSERT_NEAR(a_data[i], b_data[i], kEpsilon);
+  }
+}
+
+static void AssertTransformsEqualForTest(XRRigidTransform& a,
+                                         XRRigidTransform& b) {
+  AssertDOMPointsEqualForTest(a.position(), b.position());
+  AssertDOMPointsEqualForTest(a.orientation(), b.orientation());
+  AssertMatricesEqualForTest(a.TransformMatrix(), b.TransformMatrix());
+}
+
+static DOMPointInit* MakePointForTest(double x, double y, double z, double w) {
+  DOMPointInit* point = DOMPointInit::Create();
+  point->setX(x);
+  point->setY(y);
+  point->setZ(z);
+  point->setW(w);
+  return point;
+}
+
+static void TestComposeDecompose(DOMPointInit* position,
+                                 DOMPointInit* orientation) {
+  XRRigidTransform transform_1(position, orientation);
+  XRRigidTransform transform_2(transform_1.TransformMatrix());
+  AssertTransformsEqualForTest(transform_1, transform_2);
+}
+
+static void TestDoubleInverse(DOMPointInit* position,
+                              DOMPointInit* orientation) {
+  XRRigidTransform transform(position, orientation);
+  XRRigidTransform inverse_transform(transform.InverseTransformMatrix());
+  XRRigidTransform inverse_inverse_transform(
+      inverse_transform.InverseTransformMatrix());
+  AssertTransformsEqualForTest(transform, inverse_inverse_transform);
+}
+
+TEST(XRRigidTransformTest, Compose) {
+  DOMPointInit* position = MakePointForTest(1.0, 2.0, 3.0, 1.0);
+  DOMPointInit* orientation = MakePointForTest(0.7071068, 0.0, 0.0, 0.7071068);
+  XRRigidTransform transform(position, orientation);
+  const std::vector<double> actual_matrix =
+      GetMatrixDataForTest(transform.TransformMatrix());
+  const std::vector<double> expected_matrix{1.0, 0.0, 0.0, 0.0,  0.0, 0.0,
+                                            1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
+                                            1.0, 2.0, 3.0, 1.0};
+  for (int i = 0; i < 16; ++i) {
+    ASSERT_NEAR(actual_matrix[i], expected_matrix[i], kEpsilon);
+  }
+}
+
+TEST(XRRigidTransformTest, Decompose) {
+  XRRigidTransform transform(
+      TransformationMatrix::Create(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
+                                   -1.0, 0.0, 0.0, 1.0, 2.0, 3.0, 1.0));
+  const DOMPointReadOnly expected_position(1.0, 2.0, 3.0, 1.0);
+  const DOMPointReadOnly expected_orientation(0.7071068, 0.0, 0.0, 0.7071068);
+  AssertDOMPointsEqualForTest(transform.position(), &expected_position);
+  AssertDOMPointsEqualForTest(transform.orientation(), &expected_orientation);
+}
+
+TEST(XRRigidTransformTest, ComposeDecompose) {
+  TestComposeDecompose(MakePointForTest(1.0, -1.0, 4.0, 1.0),
+                       MakePointForTest(1.0, 0.0, 0.0, 1.0));
+}
+
+TEST(XRRigidTransformTest, ComposeDecompose2) {
+  TestComposeDecompose(
+      MakePointForTest(1.0, -1.0, 4.0, 1.0),
+      MakePointForTest(0.3701005885691383, -0.5678993882056005,
+                       0.31680366148754113, 0.663438979322567));
+}
+
+TEST(XRRigidTransformTest, DoubleInverse) {
+  TestDoubleInverse(MakePointForTest(1.0, -1.0, 4.0, 1.0),
+                    MakePointForTest(1.0, 0.0, 0.0, 1.0));
+}
+
+TEST(XRRigidTransformTest, DoubleInverse2) {
+  TestDoubleInverse(MakePointForTest(1.0, -1.0, 4.0, 1.0),
+                    MakePointForTest(0.3701005885691383, -0.5678993882056005,
+                                     0.31680366148754113, 0.663438979322567));
+}
+
+}  // namespace
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
index 73643de7..55c9b06d 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -233,8 +233,8 @@
                gfx::Transform());
 
   viz::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
-  sqs->SetAll(gfx::Transform(), bounds, bounds, bounds, is_clipped, is_opaque,
-              1.f, SkBlendMode::kSrcOver, 0);
+  sqs->SetAll(gfx::Transform(), bounds, bounds, gfx::RRectF(), bounds,
+              is_clipped, is_opaque, 1.f, SkBlendMode::kSrcOver, 0);
 
   viz::TransferableResource resource;
   auto frame_resource = std::make_unique<FrameResource>();
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc b/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
index 1a0b606..77a674a 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
@@ -110,13 +110,15 @@
 
   gfx::Rect visible_quad_rect = quad_rect;
   gfx::Rect clip_rect;
+  gfx::RRectF rounded_corner_bounds;
   bool is_clipped = false;
   float draw_opacity = 1.0f;
   int sorting_context_id = 0;
 
-  resource_updater_->AppendQuads(
-      render_pass, std::move(frame), transform, quad_rect, visible_quad_rect,
-      clip_rect, is_clipped, is_opaque, draw_opacity, sorting_context_id);
+  resource_updater_->AppendQuads(render_pass, std::move(frame), transform,
+                                 quad_rect, visible_quad_rect,
+                                 rounded_corner_bounds, clip_rect, is_clipped,
+                                 is_opaque, draw_opacity, sorting_context_id);
 }
 
 void VideoFrameResourceProvider::ReleaseFrameResources() {
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index ea6a911a..4c17940 100644
--- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -22,7 +22,6 @@
   "//third_party/blink/renderer/platform/mojo/security_origin.typemap",
   "//third_party/blink/renderer/platform/mojo/string.typemap",
   "//third_party/blink/renderer/platform/mojo/time.typemap",
-  "//third_party/blink/renderer/platform/network/encoded_form_data.typemap",
   "//third_party/blink/renderer/platform/network/http_request_headers.typemap",
   "//third_party/blink/public/platform/modules/bluetooth/bluetooth.typemap",
   "//third_party/blink/public/common/manifest/display_mode.typemap",
diff --git a/third_party/blink/renderer/platform/network/BUILD.gn b/third_party/blink/renderer/platform/network/BUILD.gn
index d895fca..27e11b8 100644
--- a/third_party/blink/renderer/platform/network/BUILD.gn
+++ b/third_party/blink/renderer/platform/network/BUILD.gn
@@ -31,8 +31,6 @@
     "content_security_policy_response_headers.h",
     "encoded_form_data.cc",
     "encoded_form_data.h",
-    "encoded_form_data_mojom_traits.cc",
-    "encoded_form_data_mojom_traits.h",
     "form_data_encoder.cc",
     "form_data_encoder.h",
     "header_field_tokenizer.cc",
@@ -90,8 +88,6 @@
 
   deps = [
     "//testing/gtest",
-  ]
-  public_deps = [
     "//third_party/blink/renderer/platform:platform",
   ]
 }
diff --git a/third_party/blink/renderer/platform/network/DEPS b/third_party/blink/renderer/platform/network/DEPS
index b2afd512..17d7eb3 100644
--- a/third_party/blink/renderer/platform/network/DEPS
+++ b/third_party/blink/renderer/platform/network/DEPS
@@ -16,7 +16,6 @@
     # For URLRequestDataJob::BuildResponse().
     "+net/url_request/url_request_data_job.h",
 
-    "+services/network/public/cpp/features.h",
     "+third_party/blink/renderer/platform/blob/blob_data.h",
     "+third_party/blink/renderer/platform/cross_thread_copier.h",
     "+third_party/blink/renderer/platform/cross_thread_functional.h",
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data.typemap b/third_party/blink/renderer/platform/network/encoded_form_data.typemap
deleted file mode 100644
index 8e0e849..0000000
--- a/third_party/blink/renderer/platform/network/encoded_form_data.typemap
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//services/network/public/mojom/url_loader.mojom"
-public_headers =
-    [ "//third_party/blink/renderer/platform/network/encoded_form_data.h" ]
-traits_headers = [ "//third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h" ]
-type_mappings =
-    [ "network.mojom.DataElement = blink::FormDataElement[move_only]" ]
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc
deleted file mode 100644
index 03cc4be..0000000
--- a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <utility>
-
-#include "third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h"
-
-#include "mojo/public/cpp/base/file_mojom_traits.h"
-#include "mojo/public/cpp/base/file_path_mojom_traits.h"
-#include "mojo/public/cpp/base/time_mojom_traits.h"
-#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
-#include "mojo/public/cpp/bindings/string_traits_wtf.h"
-#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
-#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
-#include "third_party/blink/public/platform/platform.h"
-
-namespace mojo {
-
-// static
-network::mojom::DataElementType
-StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::type(
-    const blink::FormDataElement& data) {
-  switch (data.type_) {
-    case blink::FormDataElement::kData:
-      return network::mojom::DataElementType::kBytes;
-    case blink::FormDataElement::kEncodedFile:
-      return network::mojom::DataElementType::kFile;
-    case blink::FormDataElement::kEncodedBlob: {
-      if (data.optional_blob_data_handle_)
-        return network::mojom::DataElementType::kDataPipe;
-      return network::mojom::DataElementType::kBlob;
-    }
-    case blink::FormDataElement::kDataPipe:
-      return network::mojom::DataElementType::kDataPipe;
-  }
-  NOTREACHED();
-  return network::mojom::DataElementType::kUnknown;
-}
-
-// static
-base::span<const uint8_t>
-StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::buf(
-    const blink::FormDataElement& data) {
-  return base::make_span(reinterpret_cast<const uint8_t*>(data.data_.data()),
-                         data.data_.size());
-}
-
-// static
-base::File
-StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::file(
-    const blink::FormDataElement& data) {
-  return base::File();
-}
-
-// static
-base::FilePath
-StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::path(
-    const blink::FormDataElement& data) {
-  return base::FilePath::FromUTF8Unsafe(
-      std::string(data.filename_.Utf8().data()));
-}
-
-// static
-network::mojom::blink::DataPipeGetterPtrInfo
-StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::
-    data_pipe_getter(const blink::FormDataElement& data) {
-  if (data.type_ == blink::FormDataElement::kDataPipe) {
-    if (!data.data_pipe_getter_)
-      return nullptr;
-    network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
-    (*data.data_pipe_getter_->GetPtr())
-        ->Clone(mojo::MakeRequest(&data_pipe_getter));
-    return data_pipe_getter.PassInterface();
-  }
-  if (data.type_ == blink::FormDataElement::kEncodedBlob) {
-    if (data.optional_blob_data_handle_) {
-      blink::mojom::blink::BlobPtr blob_ptr(blink::mojom::blink::BlobPtrInfo(
-          data.optional_blob_data_handle_->CloneBlobPtr()
-              .PassInterface()
-              .PassHandle(),
-          blink::mojom::blink::Blob::Version_));
-      network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr;
-      blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr));
-      return data_pipe_getter_ptr.PassInterface();
-    }
-  }
-  return nullptr;
-}
-
-// static
-base::Time
-StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::
-    expected_modification_time(const blink::FormDataElement& data) {
-  return base::Time::FromDoubleT(data.expected_file_modification_time_);
-}
-
-// static
-bool StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::
-    Read(network::mojom::DataElementDataView data,
-         blink::FormDataElement* out) {
-  network::mojom::DataElementType data_type;
-  if (!data.ReadType(&data_type)) {
-    return false;
-  }
-  out->file_start_ = data.offset();
-  out->file_length_ = data.length();
-
-  switch (data_type) {
-    case network::mojom::DataElementType::kBytes: {
-      out->type_ = blink::FormDataElement::kData;
-      // TODO:(richard.li) Delete this workaround when type of
-      // blink::FormDataElement::data_ is changed to WTF::Vector<uint8_t>
-      WTF::Vector<uint8_t> buf;
-      if (!data.ReadBuf(&buf)) {
-        return false;
-      }
-      out->data_.AppendRange(buf.begin(), buf.end());
-      break;
-    }
-    case network::mojom::DataElementType::kFile: {
-      out->type_ = blink::FormDataElement::kEncodedFile;
-      base::FilePath file_path;
-      base::Time expected_time;
-      if (!data.ReadPath(&file_path) ||
-          !data.ReadExpectedModificationTime(&expected_time)) {
-        return false;
-      }
-      out->expected_file_modification_time_ = expected_time.ToDoubleT();
-      out->filename_ =
-          WTF::String(file_path.value().data(), file_path.value().size());
-      break;
-    }
-    case network::mojom::DataElementType::kBlob: {
-      out->type_ = blink::FormDataElement::kEncodedBlob;
-      if (!data.ReadBlobUuid(&out->blob_uuid_)) {
-        return false;
-      }
-      break;
-    }
-    case network::mojom::DataElementType::kDataPipe: {
-      out->type_ = blink::FormDataElement::kDataPipe;
-      auto data_pipe_ptr_info = data.TakeDataPipeGetter<
-          network::mojom::blink::DataPipeGetterPtrInfo>();
-      DCHECK(data_pipe_ptr_info.is_valid());
-
-      network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
-      data_pipe_getter.Bind(std::move(data_pipe_ptr_info));
-      out->data_pipe_getter_ =
-          base::MakeRefCounted<blink::WrappedDataPipeGetter>(
-              std::move(data_pipe_getter));
-      break;
-    }
-    case network::mojom::DataElementType::kUnknown:
-    case network::mojom::DataElementType::kChunkedDataPipe:
-    case network::mojom::DataElementType::kRawFile:
-      NOTREACHED();
-      return false;
-  }
-  return true;
-}
-
-}  // namespace mojo
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
deleted file mode 100644
index 313a8d43..0000000
--- a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
-
-#include <string>
-
-#include "services/network/public/mojom/url_loader.mojom-blink.h"
-#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
-
-namespace mojo {
-
-template <>
-struct PLATFORM_EXPORT
-    StructTraits<network::mojom::DataElementDataView, blink::FormDataElement> {
-  static network::mojom::DataElementType type(
-      const blink::FormDataElement& data);
-
-  static base::span<const uint8_t> buf(const blink::FormDataElement& data);
-
-  static base::File file(const blink::FormDataElement& data);
-
-  static base::FilePath path(const blink::FormDataElement& data);
-
-  static const WTF::String& blob_uuid(const blink::FormDataElement& data) {
-    return data.blob_uuid_;
-  }
-
-  static network::mojom::blink::DataPipeGetterPtrInfo data_pipe_getter(
-      const blink::FormDataElement& data);
-
-  static network::mojom::blink::ChunkedDataPipeGetterPtrInfo
-  chunked_data_pipe_getter(const blink::FormDataElement& data) {
-    return nullptr;
-  }
-
-  static uint64_t offset(const blink::FormDataElement& data) {
-    return data.file_start_;
-  }
-
-  static uint64_t length(const blink::FormDataElement& data) {
-    if (data.type_ == blink::FormDataElement::kEncodedBlob &&
-        data.optional_blob_data_handle_) {
-      return data.optional_blob_data_handle_->size();
-    }
-    return data.file_length_;
-  }
-
-  static base::Time expected_modification_time(
-      const blink::FormDataElement& data);
-
-  static bool Read(network::mojom::DataElementDataView data,
-                   blink::FormDataElement* out);
-};
-
-}  // namespace mojo
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_test.cc b/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
index 5619caa..3349b1cb 100644
--- a/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
+++ b/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
@@ -2,17 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h"
-
-#include "base/sequenced_task_runner.h"
-#include "base/test/scoped_task_environment.h"
-#include "mojo/public/cpp/base/file_mojom_traits.h"
-#include "mojo/public/cpp/base/file_path_mojom_traits.h"
-#include "mojo/public/cpp/base/time_mojom_traits.h"
-#include "mojo/public/cpp/bindings/string_traits_wtf.h"
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "services/network/public/mojom/url_loader.mojom-blink.h"
-#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
@@ -105,62 +94,6 @@
   }
 }
 
-TEST(EncodedFormDataMojomTraitsTest, Roundtrips_FormDataElement) {
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  FormDataElement original1;
-  original1.type_ = blink::FormDataElement::kData;
-  original1.data_ = {'a', 'b', 'c', 'd'};
-  FormDataElement copied1;
-  EXPECT_TRUE(
-      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
-          &original1, &copied1));
-  EXPECT_EQ(original1.type_, copied1.type_);
-  EXPECT_EQ(original1.data_, copied1.data_);
-
-  FormDataElement original2;
-  original2.type_ = blink::FormDataElement::kEncodedFile;
-  original2.file_start_ = 0;
-  original2.file_length_ = 4;
-  original2.filename_ = "file.name";
-  original2.expected_file_modification_time_ = base::Time::Now().ToDoubleT();
-  FormDataElement copied2;
-  EXPECT_TRUE(
-      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
-          &original2, &copied2));
-  EXPECT_EQ(original2.type_, copied2.type_);
-  EXPECT_EQ(original2.file_start_, copied2.file_start_);
-  EXPECT_EQ(original2.file_length_, copied2.file_length_);
-  EXPECT_EQ(original2.filename_, copied2.filename_);
-  EXPECT_EQ(original2.expected_file_modification_time_,
-            copied2.expected_file_modification_time_);
-
-  FormDataElement original3;
-  original3.type_ = blink::FormDataElement::kEncodedBlob;
-  original3.blob_uuid_ = "uuid-test";
-  mojo::MessagePipe pipe;
-  original3.optional_blob_data_handle_ = BlobDataHandle::Create(
-      original3.blob_uuid_, "type-test", 100,
-      mojom::blink::BlobPtrInfo(std::move(pipe.handle0), 0));
-  FormDataElement copied3;
-  EXPECT_TRUE(
-      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
-          &original3, &copied3));
-  EXPECT_EQ(copied3.type_, blink::FormDataElement::kDataPipe);
-
-  FormDataElement original4;
-  original4.type_ = blink::FormDataElement::kDataPipe;
-  network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
-  auto request = mojo::MakeRequest(&data_pipe_getter);
-  original4.data_pipe_getter_ =
-      base::MakeRefCounted<blink::WrappedDataPipeGetter>(
-          std::move(data_pipe_getter));
-  FormDataElement copied4;
-  EXPECT_TRUE(
-      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
-          &original4, &copied4));
-  EXPECT_TRUE(copied4.data_pipe_getter_);
-}
-
 }  // namespace
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn
index 54e9954..bbc7f1d 100644
--- a/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -147,7 +147,6 @@
     "text/string_hash.h",
     "text/string_impl.cc",
     "text/string_impl.h",
-    "text/string_impl_cf.cc",
     "text/string_impl_mac.mm",
     "text/string_mac.mm",
     "text/string_operators.h",
@@ -274,10 +273,7 @@
       "Foundation.framework",
     ]
   } else {
-    sources -= [
-      "text/atomic_string_cf.cc",
-      "text/string_impl_cf.cc",
-    ]
+    sources -= [ "text/atomic_string_cf.cc" ]
   }
 
   configs -= [ "//build/config/compiler:default_symbols" ]
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc b/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc
deleted file mode 100644
index 2498c654..0000000
--- a/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2006, 2009, 2012 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
-
-#include "build/build_config.h"
-
-#if defined(OS_MACOSX)
-
-#include <CoreFoundation/CoreFoundation.h>
-#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
-#include "third_party/blink/renderer/platform/wtf/threading.h"
-#include "third_party/blink/renderer/platform/wtf/wtf.h"
-
-namespace WTF {
-
-namespace string_wrapper_cf_allocator {
-
-static StringImpl* g_current_string;
-
-static const void* Retain(const void* info) {
-  return info;
-}
-
-static void Release(const void*) {
-  NOTREACHED();
-}
-
-static CFStringRef CopyDescription(const void*) {
-  return CFSTR("WTF::String-based allocator");
-}
-
-static void* Allocate(CFIndex size, CFOptionFlags, void*) {
-  StringImpl* underlying_string = 0;
-  if (IsMainThread()) {
-    underlying_string = g_current_string;
-    if (underlying_string) {
-      g_current_string = 0;
-      underlying_string
-          ->AddRef();  // Balanced by call to deref in deallocate below.
-    }
-  }
-  StringImpl** header = static_cast<StringImpl**>(WTF::Partitions::FastMalloc(
-      sizeof(StringImpl*) + size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*)));
-  *header = underlying_string;
-  return header + 1;
-}
-
-static void* Reallocate(void* pointer, CFIndex new_size, CFOptionFlags, void*) {
-  size_t new_allocation_size = sizeof(StringImpl*) + new_size;
-  StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
-  DCHECK(!*header);
-  header = static_cast<StringImpl**>(WTF::Partitions::FastRealloc(
-      header, new_allocation_size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*)));
-  return header + 1;
-}
-
-static void DeallocateOnMainThread(void* header_pointer) {
-  StringImpl** header = static_cast<StringImpl**>(header_pointer);
-  StringImpl* underlying_string = *header;
-  DCHECK(underlying_string);
-  underlying_string->Release();  // Balanced by call to ref in allocate above.
-  WTF::Partitions::FastFree(header);
-}
-
-static void Deallocate(void* pointer, void*) {
-  StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
-  StringImpl* underlying_string = *header;
-  if (!underlying_string) {
-    WTF::Partitions::FastFree(header);
-  } else {
-    if (!IsMainThread()) {
-      internal::CallOnMainThread(&DeallocateOnMainThread, header);
-    } else {
-      underlying_string
-          ->Release();  // Balanced by call to ref in allocate above.
-      WTF::Partitions::FastFree(header);
-    }
-  }
-}
-
-static CFIndex PreferredSize(CFIndex size, CFOptionFlags, void*) {
-  // FIXME: If FastMalloc provided a "good size" callback, we'd want to use it
-  // here.  Note that this optimization would help performance for strings
-  // created with the allocator that are mutable, and those typically are only
-  // created by callers who make a new string using the old string's allocator,
-  // such as some of the call sites in CFURL.
-  return size;
-}
-
-static CFAllocatorRef Create() {
-  CFAllocatorContext context = {
-      0,        0,          Retain,     Release,      CopyDescription,
-      Allocate, Reallocate, Deallocate, PreferredSize};
-  return CFAllocatorCreate(0, &context);
-}
-
-static CFAllocatorRef Allocator() {
-  static CFAllocatorRef allocator = Create();
-  return allocator;
-}
-
-}  // namespace string_wrapper_cf_allocator
-
-base::ScopedCFTypeRef<CFStringRef> StringImpl::CreateCFString() {
-  // Since garbage collection isn't compatible with custom allocators, we
-  // can't use the NoCopy variants of CFStringCreate*() when GC is enabled.
-  if (!length_ || !IsMainThread()) {
-    if (Is8Bit())
-      return base::ScopedCFTypeRef<CFStringRef>(CFStringCreateWithBytes(
-          0, reinterpret_cast<const UInt8*>(Characters8()), length_,
-          kCFStringEncodingISOLatin1, false));
-    return base::ScopedCFTypeRef<CFStringRef>(CFStringCreateWithCharacters(
-        0, reinterpret_cast<const UniChar*>(Characters16()), length_));
-  }
-  CFAllocatorRef allocator = string_wrapper_cf_allocator::Allocator();
-
-  // Put pointer to the StringImpl in a global so the allocator can store it
-  // with the CFString.
-  DCHECK(!string_wrapper_cf_allocator::g_current_string);
-  string_wrapper_cf_allocator::g_current_string = this;
-
-  CFStringRef string;
-  if (Is8Bit())
-    string = CFStringCreateWithBytesNoCopy(
-        allocator, reinterpret_cast<const UInt8*>(Characters8()), length_,
-        kCFStringEncodingISOLatin1, false, kCFAllocatorNull);
-  else
-    string = CFStringCreateWithCharactersNoCopy(
-        allocator, reinterpret_cast<const UniChar*>(Characters16()), length_,
-        kCFAllocatorNull);
-  // CoreFoundation might not have to allocate anything, we clear currentString
-  // in case we did not execute allocate().
-  string_wrapper_cf_allocator::g_current_string = 0;
-
-  return base::ScopedCFTypeRef<CFStringRef>(string);
-}
-
-// On StringImpl creation we could check if the allocator is the
-// string_wrapper_cf_allocator.  If it is, then we could find the original
-// StringImpl and just return that.  But to do that we'd have to compute the
-// offset from CFStringRef to the allocated block; the CFStringRef is *not* at
-// the start of an allocated block. Testing shows 1000x more calls to
-// createCFString than calls to the create functions with the appropriate
-// allocator, so it's probably not urgent optimize that case.
-
-}  // namespace WTF
-
-#endif  // defined(OS_MACOSX)
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl_mac.mm b/third_party/blink/renderer/platform/wtf/text/string_impl_mac.mm
index 2e8d7d8..b4372ea 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_impl_mac.mm
+++ b/third_party/blink/renderer/platform/wtf/text/string_impl_mac.mm
@@ -25,6 +25,18 @@
 
 namespace WTF {
 
+base::ScopedCFTypeRef<CFStringRef> StringImpl::CreateCFString() {
+  return base::ScopedCFTypeRef<CFStringRef>(
+      Is8Bit()
+          ? CFStringCreateWithBytes(
+                kCFAllocatorDefault,
+                reinterpret_cast<const UInt8*>(Characters8()), length_,
+                kCFStringEncodingISOLatin1, false)
+          : CFStringCreateWithCharacters(
+                kCFAllocatorDefault,
+                reinterpret_cast<const UniChar*>(Characters16()), length_));
+}
+
 StringImpl::operator NSString*() {
   return [base::mac::CFToNSCast(CreateCFString().release()) autorelease];
 }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 01b6695..467cbc9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1786,6 +1786,9 @@
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_forward_line_br.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_forward_line_range.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_forward_line_small_line.html [ Failure ]
+crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_into_inline_block_multiline.html [ Failure ]
+crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_into_inline_block_nested.html [ Failure ]
+crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_into_inline_block_one_line.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_left_character_23_ltr.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_left_character_23_rtl.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/modify_move/move_left_character_24_ltr.html [ Failure ]
@@ -6063,8 +6066,13 @@
 crbug.com/931533 media/video-played-collapse.html [ Pass Failure ]
 crbug.com/931533 virtual/video-surface-layer/media/video-played-collapse.html [ Pass Failure ]
 
+# Flaky failures due to <object> resources not always appearing in the timeline.
+crbug.com/941482 external/wpt/resource-timing/nested-context-navigations.html [ Pass Failure ]
+
 # Sheriff 2019-03-11
 crbug.com/940136 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/auth.html [ Pass Failure ]
 
 # Test was blocking WPT importer
 crbug.com/941471 external/wpt/css/css-transforms/transform-flattening-001.html [ Pass Failure ]
+
+crbug.com/940829 external/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ Timeout Pass ]
diff --git a/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_multiline.html b/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_multiline.html
new file mode 100644
index 0000000..0c12fbd
--- /dev/null
+++ b/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_multiline.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../assert_selection.js"></script>
+<script>
+// Variations:
+// 1. Entering the inline block from left or right side
+// 2. Resolved direction of the inline block in the parent context
+// 3. Direction of the first line text inside the inline block
+// 4. Direction of the last line text inside the inline block
+
+const usesBidiAffinity = window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled;
+
+selection_test(
+  '<div contenteditable>foo|<span style="display:inline-block">bar<br>qux</span>baz</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">b|ar<br>qux</span>baz</div>',
+  'Move right, LTR resolved direction, LTR/LTR text inside');
+
+selection_test(
+  '<div contenteditable>foo<span style="display:inline-block">bar<br>qux</span>|baz</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">bar<br>qu|x</span>baz</div>',
+  'Move left, LTR resolved direction, LTR/LTR text inside');
+
+selection_test(
+  '<div contenteditable>foo|<span style="display:inline-block">\u05D0\u05D1\u05D2<br>qux</span>baz</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  usesBidiAffinity
+    ? '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1|\u05D2<br>qux</span>baz</div>'
+    : '<div contenteditable>foo<span style="display:inline-block">\u05D0|\u05D1\u05D2<br>qux</span>baz</div>',
+  'Move right, LTR resolved direction, RTL/LTR text inside');
+
+selection_test(
+  '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1\u05D2<br>qux</span>|baz</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1\u05D2<br>qu|x</span>baz</div>',
+  'Move left, LTR resolved direction, RTL/LTR text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5|<span style="display:inline-block">bar<br>qux</span>\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  usesBidiAffinity
+    ? '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">ba|r<br>qux</span>\u05D6\u05D7\u05D8</div>'
+    : '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">b|ar<br>qux</span>\u05D6\u05D7\u05D8</div>',
+  'Move left, RTL resolved direction, LTR/LTR text inside');
+
+// TODO(crbug.com/923087): BidiCaretAffinity currently fails this test case, as
+// VisiblePosition incorrectly moves the input position to "qux|".
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">bar<br>qux</span>|\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">bar<br>q|ux</span>\u05D6\u05D7\u05D8</div>',
+  'Move right, RTL resolved direction, LTR/LTR text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5|<span style="display:inline-block">\u05D0\u05D1\u05D2<br>qux</span>\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0|\u05D1\u05D2<br>qux</span>\u05D6\u05D7\u05D8</div>',
+  'Move left, RTL resolved direction, RTL/LTR text inside');
+
+// TODO(crbug.com/923087): BidiCaretAffinity currently fails this test case, as
+// VisiblePosition incorrectly moves the input position to "qux|".
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0\u05D1\u05D2<br>qux</span>|\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0\u05D1\u05D2<br>q|ux</span>\u05D6\u05D7\u05D8</div>',
+  'Move right, RTL resolved direction, RTL/LTR text inside');
+
+selection_test(
+  '<div contenteditable>foo|<span style="display:inline-block">bar<br>\u05D9\u05DA\u05DB</span>baz</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">b|ar<br>\u05D9\u05DA\u05DB</span>baz</div>',
+  'Move right, LTR resolved direction, LTR/RTL text inside');
+
+selection_test(
+  '<div contenteditable>foo<span style="display:inline-block">bar<br>\u05D9\u05DA\u05DB</span>|baz</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">bar<br>\u05D9|\u05DA\u05DB</span>baz</div>',
+  'Move left, LTR resolved direction, LTR/RTL text inside');
+
+selection_test(
+  '<div contenteditable>foo|<span style="display:inline-block">\u05D0\u05D1\u05D2<br>\u05D9\u05DA\u05DB</span>baz</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  usesBidiAffinity
+    ? '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1|\u05D2<br>\u05D9\u05DA\u05DB</span>baz</div>'
+    : '<div contenteditable>foo<span style="display:inline-block">\u05D0|\u05D1\u05D2<br>\u05D9\u05DA\u05DB</span>baz</div>',
+  'Move right, LTR resolved direction, RTL/RTL text inside');
+
+// TODO(crbug.com/923087): BidiCaretAffinity currently fails this test case, as
+// VisiblePosition incorrectly moves the input position to "JKL|".
+selection_test(
+  '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1\u05D2<br>\u05D9\u05DA\u05DB</span>|baz</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1\u05D2<br>\u05D9|\u05DA\u05DB</span>baz</div>',
+  'Move left, LTR resolved direction, RTL/RTL text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5|<span style="display:inline-block">bar<br>\u05D9\u05DA\u05DB</span>\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  usesBidiAffinity
+    ? '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">ba|r<br>\u05D9\u05DA\u05DB</span>\u05D6\u05D7\u05D8</div>'
+    : '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">b|ar<br>\u05D9\u05DA\u05DB</span>\u05D6\u05D7\u05D8</div>',
+  'Move left, RTL resolved direction, LTR/RTL text inside');
+
+// TODO(crbug.com/923087): BidiCaretAffinity currently fails this test case, as
+// VisiblePosition incorrectly moves the input position to "JKL|".
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">bar<br>\u05D9\u05DA\u05DB</span>|\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">bar<br>\u05D9\u05DA|\u05DB</span>\u05D6\u05D7\u05D8</div>',
+  'Move right, RTL resolved direction, LTR/RTL text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5|<span style="display:inline-block">\u05D0\u05D1\u05D2<br>\u05D9\u05DA\u05DB</span>\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0|\u05D1\u05D2<br>\u05D9\u05DA\u05DB</span>\u05D6\u05D7\u05D8</div>',
+  'Move left, RTL resolved direction, RTL/RTL text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0\u05D1\u05D2<br>\u05D9\u05DA\u05DB</span>|\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0\u05D1\u05D2<br>\u05D9\u05DA|\u05DB</span>\u05D6\u05D7\u05D8</div>',
+  'Move right, RTL resolved direction, RTL/RTL text inside');
+</script>
diff --git a/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_nested.html b/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_nested.html
new file mode 100644
index 0000000..36741be
--- /dev/null
+++ b/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_nested.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../assert_selection.js"></script>
+<script>
+selection_test(
+  [
+    '<div contenteditable>foo|',
+    '<span style="display:inline-block">',
+    '<div>bar</div><div>baz</div>',
+    '</span>qux</div>'
+  ].join(''),
+  selection => selection.modify('move', 'right', 'character'),
+  [
+    '<div contenteditable>foo',
+    '<span style="display:inline-block">',
+    '<div>|bar</div><div>baz</div>',
+    '</span>qux</div>'
+  ].join(''),
+  'Move right into inline block with child blocks');
+
+selection_test(
+  [
+    '<div contenteditable>foo',
+    '<span style="display:inline-block">',
+    '<div>bar</div><div>baz</div>',
+    '</span>|qux</div>'
+  ].join(''),
+  selection => selection.modify('move', 'left', 'character'),
+  [
+    '<div contenteditable>foo',
+    '<span style="display:inline-block">',
+    '<div>bar</div><div>baz|</div>',
+    '</span>qux</div>'
+  ].join(''),
+  'Move left into inline block with child blocks');
+
+selection_test(
+  [
+    '<div contenteditable>foo|',
+    '<table style="display:inline"><tbody>',
+    '<tr><td>bar</td></tr><tr><td>baz</td></tr>',
+    '</tbody></table>qux</div>'
+  ].join(''),
+  selection => selection.modify('move', 'right', 'character'),
+  [
+    '<div contenteditable>foo',
+    '<table style="display:inline"><tbody>',
+    '<tr><td>|bar</td></tr><tr><td>baz</td></tr>',
+    '</tbody></table>qux</div>'
+  ].join(''),
+  'Move right into inline table');
+
+selection_test(
+  [
+    '<div contenteditable>foo',
+    '<table style="display:inline"><tbody>',
+    '<tr><td>bar</td></tr><tr><td>baz</td></tr>',
+    '</tbody></table>|qux</div>'
+  ].join(''),
+  selection => selection.modify('move', 'left', 'character'),
+  [
+    '<div contenteditable>foo',
+    '<table style="display:inline"><tbody>',
+    '<tr><td>bar</td></tr><tr><td>baz|</td></tr>',
+    '</tbody></table>qux</div>'
+  ].join(''),
+  'Move left into inline table');
+
+selection_test(
+  [
+    '<div contenteditable>foo|',
+    '<div style="display:inline-flex">',
+    '<div>bar</div><div>baz</div>',
+    '</div>qux</div>'
+  ].join(''),
+  selection => selection.modify('move', 'right', 'character'),
+  [
+    '<div contenteditable>foo',
+    '<div style="display:inline-flex">',
+    '<div>|bar</div><div>baz</div>',
+    '</div>qux</div>'
+  ].join(''),
+  'Move right into inline flex');
+
+selection_test(
+  [
+    '<div contenteditable>foo',
+    '<div style="display:inline-flex">',
+    '<div>bar</div><div>baz</div>',
+    '</div>|qux</div>'
+  ].join(''),
+  selection => selection.modify('move', 'left', 'character'),
+  [
+    '<div contenteditable>foo',
+    '<div style="display:inline-flex">',
+    '<div>bar</div><div>baz|</div>',
+    '</div>qux</div>'
+  ].join(''),
+  'Move left into inline flex');
+</script>
diff --git a/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_one_line.html b/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_one_line.html
new file mode 100644
index 0000000..5d0a388
--- /dev/null
+++ b/third_party/blink/web_tests/editing/selection/modify_move/move_into_inline_block_one_line.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../assert_selection.js"></script>
+<script>
+// Variations:
+// 1. Entering the inline block from left or right side
+// 2. Resolved direction of the inline block in the parent context
+// 3. Direction of text inside the inline block
+
+const usesBidiAffinity = window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled;
+
+selection_test(
+  '<div contenteditable>foo|<span style="display:inline-block">bar</span>baz</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">b|ar</span>baz</div>',
+  'Move right, LTR resolved direction, LTR text inside');
+
+selection_test(
+  '<div contenteditable>foo<span style="display:inline-block">bar</span>|baz</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">ba|r</span>baz</div>',
+  'Move left, LTR resolved direction, LTR text inside');
+
+selection_test(
+  '<div contenteditable>foo|<span style="display:inline-block">\u05D0\u05D1\u05D2</span>baz</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  usesBidiAffinity
+    ? '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1|\u05D2</span>baz</div>'
+    : '<div contenteditable>foo<span style="display:inline-block">\u05D0|\u05D1\u05D2</span>baz</div>',
+  'Move right, LTR resolved direction, RTL text inside');
+
+// TODO(crbug.com/923087): BidiCaretAffinity currently fails this test case, as
+// VisiblePosition incorrectly moves the input position to "ABC|".
+selection_test(
+  '<div contenteditable>foo<span style="display:inline-block">\u05D0\u05D1\u05D2</span>|baz</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable>foo<span style="display:inline-block">\u05D0|\u05D1\u05D2</span>baz</div>',
+  'Move left, LTR resolved direction, RTL text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5|<span style="display:inline-block">bar</span>\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  usesBidiAffinity
+    ? '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">ba|r</span>\u05D6\u05D7\u05D8</div>'
+    : '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">b|ar</span>\u05D6\u05D7\u05D8</div>',
+  'Move left, RTL resolved direction, LTR text inside');
+
+// TODO(crbug.com/923087): BidiCaretAffinity currently fails this test case, as
+// VisiblePosition incorrectly moves the input position to "bar|".
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">bar</span>|\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">b|ar</span>\u05D6\u05D7\u05D8</div>',
+  'Move right, RTL resolved direction, LTR text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5|<span style="display:inline-block">\u05D0\u05D1\u05D2</span>\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'left', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0|\u05D1\u05D2</span>\u05D6\u05D7\u05D8</div>',
+  'Move left, RTL resolved direction, RTL text inside');
+
+selection_test(
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0\u05D1\u05D2</span>|\u05D6\u05D7\u05D8</div>',
+  selection => selection.modify('move', 'right', 'character'),
+  '<div contenteditable dir="rtl">\u05D3\u05D4\u05D5<span style="display:inline-block">\u05D0\u05D1|\u05D2</span>\u05D6\u05D7\u05D8</div>',
+  'Move right, RTL resolved direction, RTL text inside');
+</script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors-expected.txt
index 1f6f986..4d962af 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors-expected.txt
@@ -1,16 +1,11 @@
 Verifies that replayed CORS XHRs still have post data
-request 0: {
-  "method": "OPTIONS",
-  "url": "http://127.0.0.1:8000/inspector-protocol/network/resources/cors-return-post.php",
-  "responseData": "replied to options with Access-Control-Allow headers"
-}
-request 1: {
+POST request 0: {
   "method": "POST",
   "url": "http://127.0.0.1:8000/inspector-protocol/network/resources/cors-return-post.php",
   "postData": "{\"data\":\"test post data\"}",
   "responseData": "post data: {\"data\":\"test post data\"}"
 }
-request 2: {
+POST request 1: {
   "method": "POST",
   "url": "http://127.0.0.1:8000/inspector-protocol/network/resources/cors-return-post.php",
   "postData": "{\"data\":\"test post data\"}",
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors.js
index b75ecdf..3bb260c0 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/xhr-post-replay-cors.js
@@ -9,10 +9,7 @@
 
   function replayOptionsXhr() {
     sentReplayXhr = true;
-    const optionsRequestId =
-        Object.keys(requestsById)
-            .find(id => requestsById[id].method === 'OPTIONS');
-    dp.Network.replayXHR({requestId: optionsRequestId});
+    dp.Network.replayXHR({requestId: Object.keys(requestsById)[0]});
   }
 
   function printResultsAndFinish() {
@@ -22,8 +19,14 @@
                            delete request.wallTime;
                            return request;
                          });
-    for (let i = 0; i < requests.length; i++) {
-      testRunner.log(`request ${i}: ${JSON.stringify(requests[i], null, 2)}`);
+
+    // Ignore OPTIONS preflight requests.
+    // TODO(crbug.com/941297): Add the OPTIONS request back to the test results once this bug is fixed.
+    let postIndex = 0;
+    for (const request of requests) {
+      if (request.method !== 'POST')
+        continue;
+      testRunner.log(`POST request ${postIndex++}: ${JSON.stringify(request, null, 2)}`);
     }
     testRunner.completeTest();
   }
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
index bd478a62..af5f21f1 100644
--- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
index 7c7e327..f2469d0 100644
--- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
index 1f91feda..f38df4d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
index 61887f59..f9ea39f 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png
index a3f6eaf..483b603 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/2-dht-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
index fedf2451..06fa592 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/55-expected.png
index a388772..6762251 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png
index 1acaaf0..2368484 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png
index bea8973..746dd01 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
index 43f64621..a2a7e4f 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
index fb927f7..71492a8 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png
index a3018ee..5f34bcf 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-css-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png
index ae08025b..de03609 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png
index 26d18f7..ba74f14 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/exif-orientation-image-document-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/favicon-as-image-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/favicon-as-image-expected.png
index f14e1330..3bf27c1 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/favicon-as-image-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/favicon-as-image-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-edge-cases-expected.png
index 9879c7d..81a0dfa9 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-edge-cases-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-edge-cases-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
index aa60ad5..da6882a 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-forced-layout-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-forced-layout-expected.png
index ad4cdc6..c2ca27a3 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-forced-layout-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-forced-layout-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-responsive-image-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-responsive-image-expected.png
index 6cb1553..0e70bc8 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-responsive-image-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-responsive-image-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-styles-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-styles-expected.png
index 21cb653..5c18807 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-styles-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/feature-policy-oversized-images-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
index 1557bdf5..5da2590 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
index 8bc8e30..d18d15c 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
index b855fae2..9e0c2cc 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
index 6df2bc3..8521d6ba 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
index d11b4b18..7db3caa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
index 2123c16..7bc1471 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
index 368152fc..80ae5b78 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
index 2a102ee..6e0a7aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zero-outline-width-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zero-outline-width-expected.png
index b023864..41cdec4 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zero-outline-width-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zero-outline-width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
index d08378ab..4a7edaee 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
index 201244f5..97253a14 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
index eb32dbc..aada43e 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
index b47f876..db6cafd 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/pixel-crack-image-background-webkit-transform-scale-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/pixel-crack-image-background-webkit-transform-scale-expected.png
index b3939dc..c9b5810 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/pixel-crack-image-background-webkit-transform-scale-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/pixel-crack-image-background-webkit-transform-scale-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-expected.png
index d62551f..f6aac27 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png
index 6c0766a..7a901aeb 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-0px-images-quirk-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-10px-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-10px-images-expected.png
index 23e531e..5e04d3c 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-10px-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-10px-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-16px-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-16px-images-expected.png
index ee9b5c5f..fedf2f9 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-16px-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-16px-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-1px-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-1px-images-expected.png
index 8bbb7e4..d96e05d6 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-1px-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-1px-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png
index 42fa90e..64b9c59b 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-block-flow-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-images-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-images-expected.png
index ad300ea..92dfb008 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-images-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/rendering-broken-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scroll_customization/fast/events/touch/multi-touch-user-gesture-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/scroll_customization/fast/events/touch/multi-touch-user-gesture-expected.txt
new file mode 100644
index 0000000..61a5134
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/scroll_customization/fast/events/touch/multi-touch-user-gesture-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test user gesture behavior during multi-finger touch events. assert_equals: expected "touchstart@target1(false), touchstart@target2(false), touchmove@target1(false), touchmove@target2(false), touchend@target1(true), touchend@target2(true)" but got "touchstart@target1(false), touchstart@target2(false), touchmove@target2(false), touchmove@target1(false), touchend@target1(true), touchend@target2(true)"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.txt
new file mode 100644
index 0000000..e294d225
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.txt
@@ -0,0 +1,12 @@
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
diff --git a/third_party/blink/web_tests/platform/mac/fast/events/touch/multi-touch-user-gesture-expected.txt b/third_party/blink/web_tests/platform/mac/fast/events/touch/multi-touch-user-gesture-expected.txt
new file mode 100644
index 0000000..61a5134
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/events/touch/multi-touch-user-gesture-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test user gesture behavior during multi-finger touch events. assert_equals: expected "touchstart@target1(false), touchstart@target2(false), touchmove@target1(false), touchmove@target2(false), touchend@target1(true), touchend@target2(true)" but got "touchstart@target1(false), touchstart@target2(false), touchmove@target2(false), touchmove@target1(false), touchend@target1(true), touchend@target2(true)"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
index 396cceda0..5bbaf24 100644
--- a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
index b0ce6b9..e3d3e15 100644
--- a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
index a736ed1..ca93bc953 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
index 1caf1f5..fdb18a28 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
index 1918867..d42a7941 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/image-map-anchor-children-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
index 4f1c80e..30a3c0ba 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/image-map-anchor-children-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
index db7d836f..f5c8a71 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
index 1ff122a..2b82dcf 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
index 03884e6..e727603 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-expected.png
index 7e7ff5b7..3d9b736 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
index 96e8a35..6ab669dd 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
index 0c6a756..705df7f 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
index 7a4bdb74..890e7744 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
index 47a71898..fa4e40f3 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
index 281176ed..3de2dbf 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
index 50a38bc..a3d58a6 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
index 1495b74..a3a6752 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
index 9b79ee5..44982e9 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
index 0aeb2da..e59f7e4f 100644
--- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-03-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
index 356ea4f85..eb1456c4 100644
--- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1-SE/filters-image-05-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
index 5bdaf81..2616aa00 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-diff-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
index c631562..c7bd016 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/cross-fade-svg-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
index 4769870..3c75d67 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
index 3be9597..94ac255 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
index e713bcb..8f58f48 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-in-positioned-container-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
index 2834530..5b6e63e 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-outline-color-not-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
index 49d3b534..efca9837 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-paint-root-offset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
index 4c4385c..425e555e 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-with-scale-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
index cccfc99..7e99a0be 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-focus-ring-zoom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
index 2858fa6..b3756a6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
index 6929b29..4274da1 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-overflowing-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
index 066f33b..8414dc3 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/imagemap-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png b/third_party/blink/web_tests/platform/win7/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
new file mode 100644
index 0000000..266834369
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.txt
new file mode 100644
index 0000000..e294d225
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/exotic-color-space/images/feature-policy-oversized-images-expected.txt
@@ -0,0 +1,12 @@
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
+CONSOLE ERROR: Feature policy violation: oversized-images is not allowed in this document.
diff --git a/third_party/blink/web_tests/svg/filters/feImage-preserveAspectRatio-all-expected.png b/third_party/blink/web_tests/svg/filters/feImage-preserveAspectRatio-all-expected.png
index 7c626e7..d52e71d 100644
--- a/third_party/blink/web_tests/svg/filters/feImage-preserveAspectRatio-all-expected.png
+++ b/third_party/blink/web_tests/svg/filters/feImage-preserveAspectRatio-all-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/filters/feImage-preserveAspectratio-expected.png b/third_party/blink/web_tests/svg/filters/feImage-preserveAspectratio-expected.png
index cfe069d..6336afe1 100644
--- a/third_party/blink/web_tests/svg/filters/feImage-preserveAspectratio-expected.png
+++ b/third_party/blink/web_tests/svg/filters/feImage-preserveAspectratio-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/filters/filteredImage-expected.png b/third_party/blink/web_tests/svg/filters/filteredImage-expected.png
index fec75dc..aa1a9b3 100644
--- a/third_party/blink/web_tests/svg/filters/filteredImage-expected.png
+++ b/third_party/blink/web_tests/svg/filters/filteredImage-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/image-invert-expected.png b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/image-invert-expected.png
index bc6b96e..2aa2c0b8 100644
--- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/image-invert-expected.png
+++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/image-invert-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-invalidation-expected.png b/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-invalidation-expected.png
index 212a5e11..e2cbbdf 100644
--- a/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-invalidation-expected.png
+++ b/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-invalidation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-overflow-position-expected.png b/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-overflow-position-expected.png
index 0e6cc0a..42c84084 100644
--- a/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-overflow-position-expected.png
+++ b/third_party/blink/web_tests/virtual/exotic-color-space/images/cross-fade-overflow-position-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png b/third_party/blink/web_tests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
index 45c5653..3a286c2 100644
--- a/third_party/blink/web_tests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
+++ b/third_party/blink/web_tests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
Binary files differ
diff --git a/third_party/custom_tabs_client/BUILD.gn b/third_party/custom_tabs_client/BUILD.gn
index fd873ac9..61f9e6e9 100644
--- a/third_party/custom_tabs_client/BUILD.gn
+++ b/third_party/custom_tabs_client/BUILD.gn
@@ -33,8 +33,8 @@
     ":custom_tabs_client_shared_java",
     ":custom_tabs_support_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
-    "//third_party/android_deps:android_support_annotations_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   chromium_code = false
 }
@@ -80,9 +80,9 @@
   ]
   deps = [
     ":custom_tabs_support_resources",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_compat_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
   ]
   srcjar_deps = [ ":chrome_custom_tabs_service_aidl" ]
   android_manifest_for_lint = "src/customtabs/AndroidManifest.xml"
diff --git a/third_party/espresso/BUILD.gn b/third_party/espresso/BUILD.gn
index 1307e3f9..6439e726 100644
--- a/third_party/espresso/BUILD.gn
+++ b/third_party/espresso/BUILD.gn
@@ -33,7 +33,7 @@
   jar_path = "lib/espresso-core-release-no-dep.jar"
   deps = [
     ":espresso_idling_java",
-    "//third_party/android_deps:android_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:javax_inject_javax_inject_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/guava:guava_android_java",
diff --git a/third_party/feed/BUILD.gn b/third_party/feed/BUILD.gn
index 66f3819f..ea77c29 100644
--- a/third_party/feed/BUILD.gn
+++ b/third_party/feed/BUILD.gn
@@ -59,10 +59,10 @@
     ":piet_resources",
     ":shared_stream_publicapi_menumeasurer_resources",
     ":sharedstream_contextmenumanager_resources",
-    "//third_party/android_deps:android_support_annotations_java",
-    "//third_party/android_deps:android_support_cardview_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_cardview_v7_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_lite_java",
     "//third_party/android_deps:javax_inject_javax_inject_java",
     "//third_party/jsr-305:jsr_305_javalib",
diff --git a/third_party/inspector_protocol/BUILD.gn b/third_party/inspector_protocol/BUILD.gn
index 0cf1a98..ddbe626 100644
--- a/third_party/inspector_protocol/BUILD.gn
+++ b/third_party/inspector_protocol/BUILD.gn
@@ -2,109 +2,15 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# All build targets below are experimental and not used within the
-# Chromium / V8 / etc. trees yet thus far. Do not depend on anything.
-
-import("//testing/test.gni")
-
-static_library("json_parser") {
+static_library("encoding") {
   sources = [
-    "encoding/json_parser.cc",
-    "encoding/json_parser.h",
-    "encoding/json_parser_handler.h",
-    "encoding/platform.h",
-    "encoding/span.h",
-    "encoding/status.h",
-    "encoding/str_util.cc",
-    "encoding/str_util.h",
+    "encoding/encoding.cc",
+    "encoding/encoding.h",
   ]
 }
 
-static_library("linux_dev_platform") {
-  sources = [
-    "encoding/linux_dev_platform.cc",
-    "encoding/linux_dev_platform.h",
-    "encoding/platform.h",
-  ]
-}
+# encoding/encoding_test.cc:
+# There's no target for this file here, instead it is included
+# in //content/test:content_unittest
+# via //content/browser/devtools:inspector_protocol_encoding_test.
 
-test("json_parser_test") {
-  sources = [
-    "encoding/json_parser_test.cc",
-  ]
-  deps = [
-    ":json_parser",
-    ":linux_dev_platform",
-    "//base",
-    "//third_party/googletest:gmock",
-    "//third_party/googletest:gtest",
-    "//third_party/googletest:gtest_main",
-  ]
-}
-
-static_library("cbor") {
-  sources = [
-    "encoding/cbor.cc",
-    "encoding/cbor.h",
-    "encoding/json_parser_handler.h",
-    "encoding/span.h",
-    "encoding/status.h",
-  ]
-  deps = [
-    ":json_parser",
-  ]
-}
-
-test("cbor_test") {
-  sources = [
-    "encoding/cbor_test.cc",
-  ]
-  deps = [
-    ":cbor",
-    ":json_parser",
-    ":json_std_string_writer",
-    ":linux_dev_platform",
-    "//base",
-    "//third_party/googletest:gmock",
-    "//third_party/googletest:gtest",
-    "//third_party/googletest:gtest_main",
-  ]
-}
-
-test("span_test") {
-  sources = [
-    "encoding/span.h",
-    "encoding/span_test.cc",
-  ]
-  deps = [
-    "//base",
-    "//third_party/googletest:gmock",
-    "//third_party/googletest:gtest",
-    "//third_party/googletest:gtest_main",
-  ]
-}
-
-static_library("json_std_string_writer") {
-  sources = [
-    "encoding/json_parser_handler.h",
-    "encoding/json_std_string_writer.cc",
-    "encoding/json_std_string_writer.h",
-    "encoding/platform.h",
-    "encoding/span.h",
-    "encoding/status.h",
-  ]
-}
-
-test("json_std_string_writer_test") {
-  sources = [
-    "encoding/json_std_string_writer_test.cc",
-  ]
-  deps = [
-    ":json_std_string_writer",
-    ":linux_dev_platform",
-    "//base",
-    "//third_party/googletest:gmock",
-    "//third_party/googletest:gtest",
-    "//third_party/googletest:gtest_main",
-  ]
-}
diff --git a/third_party/inspector_protocol/DEPS b/third_party/inspector_protocol/DEPS
index 81c9b082..20785c0 100644
--- a/third_party/inspector_protocol/DEPS
+++ b/third_party/inspector_protocol/DEPS
@@ -6,7 +6,7 @@
 specific_include_rules = {
   '^.*_test\.cc$': [
     '+base',
-    '+gmock',
-    '+gtest',
+    '+testing/gtest/include',
+    '+testing/gmock/include',
   ],
 }
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium
index 89f754b6..f68de23 100644
--- a/third_party/inspector_protocol/README.chromium
+++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@
 Short Name: inspector_protocol
 URL: https://chromium.googlesource.com/deps/inspector_protocol/
 Version: 0
-Revision: be5f927f77f7d4670a02f16ed026db0a3768980a
+Revision: a6bdf8a7cc95ee954ba2f701d10f4ecf03e86539
 License: BSD
 License File: LICENSE
 Security Critical: no
diff --git a/third_party/inspector_protocol/code_generator.py b/third_party/inspector_protocol/code_generator.py
index fb9959d..18777d0f 100755
--- a/third_party/inspector_protocol/code_generator.py
+++ b/third_party/inspector_protocol/code_generator.py
@@ -632,7 +632,7 @@
             "Array_h.template",
             "DispatcherBase_h.template",
             "Parser_h.template",
-            "CBOR_h.template",
+            "encoding_h.template",
         ]
 
         protocol_cpp_templates = [
@@ -642,7 +642,7 @@
             "Object_cpp.template",
             "DispatcherBase_cpp.template",
             "Parser_cpp.template",
-            "CBOR_cpp.template",
+            "encoding_cpp.template",
         ]
 
         forward_h_templates = [
diff --git a/third_party/inspector_protocol/encoding/cbor.cc b/third_party/inspector_protocol/encoding/cbor.cc
deleted file mode 100644
index f771f5b..0000000
--- a/third_party/inspector_protocol/encoding/cbor.cc
+++ /dev/null
@@ -1,821 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cbor.h"
-
-#include <cassert>
-#include <limits>
-#include "json_parser_handler.h"
-
-namespace inspector_protocol {
-using namespace cbor;
-
-namespace {
-
-// See RFC 7049 Section 2.3, Table 2.
-static constexpr uint8_t kEncodedTrue =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 21);
-static constexpr uint8_t kEncodedFalse =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 20);
-static constexpr uint8_t kEncodedNull =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 22);
-static constexpr uint8_t kInitialByteForDouble =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 27);
-
-}  // namespace
-
-uint8_t EncodeTrue() { return kEncodedTrue; }
-uint8_t EncodeFalse() { return kEncodedFalse; }
-uint8_t EncodeNull() { return kEncodedNull; }
-
-uint8_t EncodeIndefiniteLengthArrayStart() {
-  return kInitialByteIndefiniteLengthArray;
-}
-
-uint8_t EncodeIndefiniteLengthMapStart() {
-  return kInitialByteIndefiniteLengthMap;
-}
-
-uint8_t EncodeStop() { return kStopByte; }
-
-namespace {
-// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for
-// arbitrary binary data encoded as BYTE_STRING.
-static constexpr uint8_t kExpectedConversionToBase64Tag =
-    EncodeInitialByte(MajorType::TAG, 22);
-
-// When parsing CBOR, we limit recursion depth for objects and arrays
-// to this constant.
-static constexpr int kStackLimit = 1000;
-
-// Writes the bytes for |v| to |out|, starting with the most significant byte.
-// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
-template <typename T>
-void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) {
-  for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes)
-    out->push_back(0xff & (v >> (shift_bytes * 8)));
-}
-}  // namespace
-
-namespace cbor_internals {
-// Writes the start of a token with |type|. The |value| may indicate the size,
-// or it may be the payload if the value is an unsigned integer.
-void WriteTokenStart(MajorType type, uint64_t value,
-                     std::vector<uint8_t>* encoded) {
-  if (value < 24) {
-    // Values 0-23 are encoded directly into the additional info of the
-    // initial byte.
-    encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value));
-    return;
-  }
-  if (value <= std::numeric_limits<uint8_t>::max()) {
-    // Values 24-255 are encoded with one initial byte, followed by the value.
-    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte));
-    encoded->push_back(value);
-    return;
-  }
-  if (value <= std::numeric_limits<uint16_t>::max()) {
-    // Values 256-65535: 1 initial byte + 2 bytes payload.
-    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes));
-    WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded);
-    return;
-  }
-  if (value <= std::numeric_limits<uint32_t>::max()) {
-    // 32 bit uint: 1 initial byte + 4 bytes payload.
-    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes));
-    WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value),
-                                                 encoded);
-    return;
-  }
-  // 64 bit uint: 1 initial byte + 8 bytes payload.
-  encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes));
-  WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded);
-}
-}  // namespace cbor_internals
-
-namespace {
-// Extracts sizeof(T) bytes from |in| to extract a value of type T
-// (e.g. uint64_t, uint32_t, ...), most significant byte first.
-// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
-template <typename T>
-T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
-  assert(static_cast<std::size_t>(in.size()) >= sizeof(T));
-  T result = 0;
-  for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
-    result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
-  return result;
-}
-}  // namespace
-
-namespace cbor_internals {
-int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
-  if (bytes.empty()) return -1;
-  uint8_t initial_byte = bytes[0];
-  *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
-
-  uint8_t additional_information = initial_byte & kAdditionalInformationMask;
-  if (additional_information < 24) {
-    // Values 0-23 are encoded directly into the additional info of the
-    // initial byte.
-    *value = additional_information;
-    return 1;
-  }
-  if (additional_information == kAdditionalInformation1Byte) {
-    // Values 24-255 are encoded with one initial byte, followed by the value.
-    if (bytes.size() < 2) return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
-    return 2;
-  }
-  if (additional_information == kAdditionalInformation2Bytes) {
-    // Values 256-65535: 1 initial byte + 2 bytes payload.
-    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t))
-      return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
-    return 3;
-  }
-  if (additional_information == kAdditionalInformation4Bytes) {
-    // 32 bit uint: 1 initial byte + 4 bytes payload.
-    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t))
-      return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
-    return 5;
-  }
-  if (additional_information == kAdditionalInformation8Bytes) {
-    // 64 bit uint: 1 initial byte + 8 bytes payload.
-    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t))
-      return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
-    return 9;
-  }
-  return -1;
-}
-}  // namespace cbor_internals
-
-using cbor_internals::WriteTokenStart;
-using cbor_internals::ReadTokenStart;
-
-void EncodeInt32(int32_t value, std::vector<uint8_t>* out) {
-  if (value >= 0) {
-    WriteTokenStart(MajorType::UNSIGNED, value, out);
-  } else {
-    uint64_t representation = static_cast<uint64_t>(-(value + 1));
-    WriteTokenStart(MajorType::NEGATIVE, representation, out);
-  }
-}
-
-void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) {
-  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
-  WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
-  // When emitting UTF16 characters, we always write the least significant byte
-  // first; this is because it's the native representation for X86.
-  // TODO(johannes): Implement a more efficient thing here later, e.g.
-  // casting *iff* the machine has this byte order.
-  // The wire format for UTF16 chars will probably remain the same
-  // (least significant byte first) since this way we can have
-  // golden files, unittests, etc. that port easily and universally.
-  // See also:
-  // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
-  for (const uint16_t two_bytes : in) {
-    out->push_back(two_bytes);
-    out->push_back(two_bytes >> 8);
-  }
-}
-
-void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) {
-  WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(in.size_bytes()),
-                  out);
-  out->insert(out->end(), in.begin(), in.end());
-}
-
-void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) {
-  for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) {
-    if (latin1[ii] <= 127)
-      continue;
-    // If there's at least one non-ASCII char, convert to UTF8.
-    std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii);
-    for (; ii < latin1.size(); ++ii) {
-      if (latin1[ii] <= 127) {
-        utf8.push_back(latin1[ii]);
-      } else {
-        // 0xC0 means it's a UTF8 sequence with 2 bytes.
-        utf8.push_back((latin1[ii] >> 6) | 0xc0);
-        utf8.push_back((latin1[ii] | 0x80) & 0xbf);
-      }
-    }
-    EncodeString8(span<uint8_t>(utf8.data(), utf8.size()), out);
-    return;
-  }
-  EncodeString8(latin1, out);
-}
-
-void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) {
-  // If there's at least one non-ASCII char, encode as STRING16 (UTF16).
-  for (uint16_t ch : utf16) {
-    if (ch <= 127)
-      continue;
-    EncodeString16(utf16, out);
-    return;
-  }
-  // It's all US-ASCII, strip out every second byte and encode as UTF8.
-  WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(utf16.size()), out);
-  out->insert(out->end(), utf16.begin(), utf16.end());
-}
-
-void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) {
-  out->push_back(kExpectedConversionToBase64Tag);
-  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
-  WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
-  out->insert(out->end(), in.begin(), in.end());
-}
-
-// A double is encoded with a specific initial byte
-// (kInitialByteForDouble) plus the 64 bits of payload for its value.
-constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
-
-// An envelope is encoded with a specific initial byte
-// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
-// bit wide length, plus a 32 bit length for that string.
-constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
-
-void EncodeDouble(double value, std::vector<uint8_t>* out) {
-  // The additional_info=27 indicates 64 bits for the double follow.
-  // See RFC 7049 Section 2.3, Table 1.
-  out->push_back(kInitialByteForDouble);
-  union {
-    double from_double;
-    uint64_t to_uint64;
-  } reinterpret;
-  reinterpret.from_double = value;
-  WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out);
-}
-
-void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) {
-  assert(byte_size_pos_ == 0);
-  out->push_back(kInitialByteForEnvelope);
-  out->push_back(kInitialByteFor32BitLengthByteString);
-  byte_size_pos_ = out->size();
-  out->resize(out->size() + sizeof(uint32_t));
-}
-
-bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) {
-  assert(byte_size_pos_ != 0);
-  // The byte size is the size of the payload, that is, all the
-  // bytes that were written past the byte size position itself.
-  uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t));
-  // We store exactly 4 bytes, so at most INT32MAX, with most significant
-  // byte first.
-  if (byte_size > std::numeric_limits<uint32_t>::max()) return false;
-  for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0;
-       --shift_bytes) {
-    (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8));
-  }
-  return true;
-}
-
-namespace {
-class JSONToCBOREncoder : public JSONParserHandler {
- public:
-  JSONToCBOREncoder(std::vector<uint8_t>* out, Status* status)
-      : out_(out), status_(status) {
-    *status_ = Status();
-  }
-
-  void HandleObjectBegin() override {
-    envelopes_.emplace_back();
-    envelopes_.back().EncodeStart(out_);
-    out_->push_back(kInitialByteIndefiniteLengthMap);
-  }
-
-  void HandleObjectEnd() override {
-    out_->push_back(kStopByte);
-    assert(!envelopes_.empty());
-    envelopes_.back().EncodeStop(out_);
-    envelopes_.pop_back();
-  }
-
-  void HandleArrayBegin() override {
-    envelopes_.emplace_back();
-    envelopes_.back().EncodeStart(out_);
-    out_->push_back(kInitialByteIndefiniteLengthArray);
-  }
-
-  void HandleArrayEnd() override {
-    out_->push_back(kStopByte);
-    assert(!envelopes_.empty());
-    envelopes_.back().EncodeStop(out_);
-    envelopes_.pop_back();
-  }
-
-  void HandleString8(span<uint8_t> chars) override {
-    EncodeString8(chars, out_);
-  }
-
-  void HandleString16(span<uint16_t> chars) override {
-    for (uint16_t ch : chars) {
-      if (ch >= 0x7f) {
-        // If there's at least one non-7bit character, we encode as UTF16.
-        EncodeString16(chars, out_);
-        return;
-      }
-    }
-    std::vector<uint8_t> sevenbit_chars(chars.begin(), chars.end());
-    EncodeString8(span<uint8_t>(sevenbit_chars.data(), sevenbit_chars.size()),
-                  out_);
-  }
-
-  void HandleBinary(std::vector<uint8_t> bytes) override {
-    EncodeBinary(span<uint8_t>(bytes.data(), bytes.size()), out_);
-  }
-
-  void HandleDouble(double value) override { EncodeDouble(value, out_); }
-
-  void HandleInt32(int32_t value) override { EncodeInt32(value, out_); }
-
-  void HandleBool(bool value) override {
-    // See RFC 7049 Section 2.3, Table 2.
-    out_->push_back(value ? kEncodedTrue : kEncodedFalse);
-  }
-
-  void HandleNull() override {
-    // See RFC 7049 Section 2.3, Table 2.
-    out_->push_back(kEncodedNull);
-  }
-
-  void HandleError(Status error) override {
-    assert(!error.ok());
-    *status_ = error;
-    out_->clear();
-  }
-
- private:
-  std::vector<uint8_t>* out_;
-  std::vector<EnvelopeEncoder> envelopes_;
-  Status* status_;
-};
-}  // namespace
-
-std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder(
-    std::vector<uint8_t>* out, Status* status) {
-  return std::unique_ptr<JSONParserHandler>(new JSONToCBOREncoder(out, status));
-}
-
-namespace {
-// Below are three parsing routines for CBOR, which cover enough
-// to roundtrip JSON messages.
-bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer,
-              JSONParserHandler* out);
-bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out);
-bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out);
-
-void ParseUTF16String(CBORTokenizer* tokenizer, JSONParserHandler* out) {
-  std::vector<uint16_t> value;
-  span<uint8_t> rep = tokenizer->GetString16WireRep();
-  for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2)
-    value.push_back((rep[ii + 1] << 8) | rep[ii]);
-  out->HandleString16(span<uint16_t>(value.data(), value.size()));
-  tokenizer->Next();
-}
-
-bool ParseUTF8String(CBORTokenizer* tokenizer, JSONParserHandler* out) {
-  assert(tokenizer->TokenTag() == CBORTokenTag::STRING8);
-  out->HandleString8(tokenizer->GetString8());
-  tokenizer->Next();
-  return true;
-}
-
-bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out) {
-  if (stack_depth > kStackLimit) {
-    out->HandleError(
-        Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos});
-    return false;
-  }
-  // Skip past the envelope to get to what's inside.
-  if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE)
-    tokenizer->EnterEnvelope();
-  switch (tokenizer->TokenTag()) {
-    case CBORTokenTag::ERROR_VALUE:
-      out->HandleError(tokenizer->Status());
-      return false;
-    case CBORTokenTag::DONE:
-      out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
-                              tokenizer->Status().pos});
-      return false;
-    case CBORTokenTag::TRUE_VALUE:
-      out->HandleBool(true);
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::FALSE_VALUE:
-      out->HandleBool(false);
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::NULL_VALUE:
-      out->HandleNull();
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::INT32:
-      out->HandleInt32(tokenizer->GetInt32());
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::DOUBLE:
-      out->HandleDouble(tokenizer->GetDouble());
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::STRING8:
-      return ParseUTF8String(tokenizer, out);
-    case CBORTokenTag::STRING16:
-      ParseUTF16String(tokenizer, out);
-      return true;
-    case CBORTokenTag::BINARY: {
-      span<uint8_t> binary = tokenizer->GetBinary();
-      out->HandleBinary(std::vector<uint8_t>(binary.begin(), binary.end()));
-      tokenizer->Next();
-      return true;
-    }
-    case CBORTokenTag::MAP_START:
-      return ParseMap(stack_depth + 1, tokenizer, out);
-    case CBORTokenTag::ARRAY_START:
-      return ParseArray(stack_depth + 1, tokenizer, out);
-    default:
-      out->HandleError(
-          Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos});
-      return false;
-  }
-}
-
-// |bytes| must start with the indefinite length array byte, so basically,
-// ParseArray may only be called after an indefinite length array has been
-// detected.
-bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out) {
-  assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
-  tokenizer->Next();
-  out->HandleArrayBegin();
-  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
-    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
-      out->HandleError(
-          Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos});
-      return false;
-    }
-    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
-      out->HandleError(tokenizer->Status());
-      return false;
-    }
-    // Parse value.
-    if (!ParseValue(stack_depth, tokenizer, out)) return false;
-  }
-  out->HandleArrayEnd();
-  tokenizer->Next();
-  return true;
-}
-
-// |bytes| must start with the indefinite length array byte, so basically,
-// ParseArray may only be called after an indefinite length array has been
-// detected.
-bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer,
-              JSONParserHandler* out) {
-  assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START);
-  out->HandleObjectBegin();
-  tokenizer->Next();
-  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
-    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
-      out->HandleError(
-          Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos});
-      return false;
-    }
-    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
-      out->HandleError(tokenizer->Status());
-      return false;
-    }
-    // Parse key.
-    if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
-      if (!ParseUTF8String(tokenizer, out))
-        return false;
-    } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
-      ParseUTF16String(tokenizer, out);
-    } else {
-      out->HandleError(
-          Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos});
-      return false;
-    }
-    // Parse value.
-    if (!ParseValue(stack_depth, tokenizer, out)) return false;
-  }
-  out->HandleObjectEnd();
-  tokenizer->Next();
-  return true;
-}
-}  // namespace
-
-void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out) {
-  if (bytes.empty()) {
-    json_out->HandleError(Status{Error::CBOR_NO_INPUT, 0});
-    return;
-  }
-  if (bytes[0] != kInitialByteForEnvelope) {
-    json_out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0});
-    return;
-  }
-  CBORTokenizer tokenizer(bytes);
-  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
-    json_out->HandleError(tokenizer.Status());
-    return;
-  }
-  // We checked for the envelope start byte above, so the tokenizer
-  // must agree here, since it's not an error.
-  assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE);
-  tokenizer.EnterEnvelope();
-  if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) {
-    json_out->HandleError(
-        Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos});
-    return;
-  }
-  if (!ParseMap(/*stack_depth=*/1, &tokenizer, json_out)) return;
-  if (tokenizer.TokenTag() == CBORTokenTag::DONE) return;
-  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
-    json_out->HandleError(tokenizer.Status());
-    return;
-  }
-  json_out->HandleError(
-      Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos});
-}
-
-CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) {
-  ReadNextToken(/*enter_envelope=*/false);
-}
-CBORTokenizer::~CBORTokenizer() {}
-
-CBORTokenTag CBORTokenizer::TokenTag() const { return token_tag_; }
-
-void CBORTokenizer::Next() {
-  if (token_tag_ == CBORTokenTag::ERROR_VALUE || token_tag_ == CBORTokenTag::DONE)
-    return;
-  ReadNextToken(/*enter_envelope=*/false);
-}
-
-void CBORTokenizer::EnterEnvelope() {
-  assert(token_tag_ == CBORTokenTag::ENVELOPE);
-  ReadNextToken(/*enter_envelope=*/true);
-}
-
-Status CBORTokenizer::Status() const { return status_; }
-
-int32_t CBORTokenizer::GetInt32() const {
-  assert(token_tag_ == CBORTokenTag::INT32);
-  // The range checks happen in ::ReadNextToken().
-  return static_cast<uint32_t>(
-      token_start_type_ == MajorType::UNSIGNED
-          ? token_start_internal_value_
-          : -static_cast<int64_t>(token_start_internal_value_) - 1);
-}
-
-double CBORTokenizer::GetDouble() const {
-  assert(token_tag_ == CBORTokenTag::DOUBLE);
-  union {
-    uint64_t from_uint64;
-    double to_double;
-  } reinterpret;
-  reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>(
-      bytes_.subspan(status_.pos + 1));
-  return reinterpret.to_double;
-}
-
-span<uint8_t> CBORTokenizer::GetString8() const {
-  assert(token_tag_ == CBORTokenTag::STRING8);
-  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
-}
-
-span<uint8_t> CBORTokenizer::GetString16WireRep() const {
-  assert(token_tag_ == CBORTokenTag::STRING16);
-  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
-}
-
-span<uint8_t> CBORTokenizer::GetBinary() const {
-  assert(token_tag_ == CBORTokenTag::BINARY);
-  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
-}
-
-void CBORTokenizer::ReadNextToken(bool enter_envelope) {
-  if (enter_envelope) {
-    status_.pos += kEncodedEnvelopeHeaderSize;
-  } else {
-    status_.pos =
-        status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_;
-  }
-  status_.error = Error::OK;
-  if (status_.pos >= bytes_.size()) {
-    token_tag_ = CBORTokenTag::DONE;
-    return;
-  }
-  switch (bytes_[status_.pos]) {
-    case kStopByte:
-      SetToken(CBORTokenTag::STOP, 1);
-      return;
-    case kInitialByteIndefiniteLengthMap:
-      SetToken(CBORTokenTag::MAP_START, 1);
-      return;
-    case kInitialByteIndefiniteLengthArray:
-      SetToken(CBORTokenTag::ARRAY_START, 1);
-      return;
-    case kEncodedTrue:
-      SetToken(CBORTokenTag::TRUE_VALUE, 1);
-      return;
-    case kEncodedFalse:
-      SetToken(CBORTokenTag::FALSE_VALUE, 1);
-      return;
-    case kEncodedNull:
-      SetToken(CBORTokenTag::NULL_VALUE, 1);
-      return;
-    case kExpectedConversionToBase64Tag: {  // BINARY
-      int8_t bytes_read =
-          ReadTokenStart(bytes_.subspan(status_.pos + 1), &token_start_type_,
-                         &token_start_internal_value_);
-      int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_;
-      if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
-          status_.pos + token_byte_length > bytes_.size()) {
-        SetError(Error::CBOR_INVALID_BINARY);
-        return;
-      }
-      SetToken(CBORTokenTag::BINARY,
-               static_cast<std::ptrdiff_t>(token_byte_length));
-      return;
-    }
-    case kInitialByteForDouble: {  // DOUBLE
-      if (status_.pos + kEncodedDoubleSize > bytes_.size()) {
-        SetError(Error::CBOR_INVALID_DOUBLE);
-        return;
-      }
-      SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize);
-      return;
-    }
-    case kInitialByteForEnvelope: {  // ENVELOPE
-      if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) {
-        SetError(Error::CBOR_INVALID_ENVELOPE);
-        return;
-      }
-      // The envelope must be a byte string with 32 bit length.
-      if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) {
-        SetError(Error::CBOR_INVALID_ENVELOPE);
-        return;
-      }
-      // Read the length of the byte string.
-      token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
-          bytes_.subspan(status_.pos + 2));
-      // Make sure the payload is contained within the message.
-      if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize +
-              status_.pos >
-          static_cast<std::size_t>(bytes_.size())) {
-        SetError(Error::CBOR_INVALID_ENVELOPE);
-        return;
-      }
-      auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-      SetToken(CBORTokenTag::ENVELOPE,
-               kEncodedEnvelopeHeaderSize + length);
-      return;
-    }
-    default: {
-      span<uint8_t> remainder =
-          bytes_.subspan(status_.pos, bytes_.size() - status_.pos);
-      assert(!remainder.empty());
-      int8_t token_start_length = ReadTokenStart(remainder, &token_start_type_,
-                                                 &token_start_internal_value_);
-      bool success = token_start_length != -1;
-      switch (token_start_type_) {
-        case MajorType::UNSIGNED:  // INT32.
-          if (!success || std::numeric_limits<int32_t>::max() <
-                              token_start_internal_value_) {
-            SetError(Error::CBOR_INVALID_INT32);
-            return;
-          }
-          SetToken(CBORTokenTag::INT32, token_start_length);
-          return;
-        case MajorType::NEGATIVE:  // INT32.
-          if (!success ||
-              std::numeric_limits<int32_t>::min() >
-                  -static_cast<int64_t>(token_start_internal_value_) - 1) {
-            SetError(Error::CBOR_INVALID_INT32);
-            return;
-          }
-          SetToken(CBORTokenTag::INT32, token_start_length);
-          return;
-        case MajorType::STRING: {  // STRING8.
-          if (!success || remainder.size() < static_cast<int64_t>(
-                                                 token_start_internal_value_)) {
-            SetError(Error::CBOR_INVALID_STRING8);
-            return;
-          }
-          auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-          SetToken(CBORTokenTag::STRING8, token_start_length + length);
-          return;
-        }
-        case MajorType::BYTE_STRING: {  // STRING16.
-          if (!success ||
-              remainder.size() <
-                  static_cast<int64_t>(token_start_internal_value_) ||
-              // Must be divisible by 2 since UTF16 is 2 bytes per character.
-              token_start_internal_value_ & 1) {
-            SetError(Error::CBOR_INVALID_STRING16);
-            return;
-          }
-          auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-          SetToken(CBORTokenTag::STRING16, token_start_length + length);
-          return;
-        }
-        case MajorType::ARRAY:
-        case MajorType::MAP:
-        case MajorType::TAG:
-        case MajorType::SIMPLE_VALUE:
-          SetError(Error::CBOR_UNSUPPORTED_VALUE);
-          return;
-      }
-    }
-  }
-}
-
-void CBORTokenizer::SetToken(CBORTokenTag token_tag,
-                             std::ptrdiff_t token_byte_length) {
-  token_tag_ = token_tag;
-  token_byte_length_ = token_byte_length;
-}
-
-void CBORTokenizer::SetError(Error error) {
-  token_tag_ = CBORTokenTag::ERROR_VALUE;
-  status_.error = error;
-}
-
-#if 0
-void DumpCBOR(span<uint8_t> cbor) {
-  std::string indent;
-  CBORTokenizer tokenizer(cbor);
-  while (true) {
-    fprintf(stderr, "%s", indent.c_str());
-    switch (tokenizer.TokenTag()) {
-      case CBORTokenTag::ERROR_VALUE:
-        fprintf(stderr, "ERROR {status.error=%d, status.pos=%ld}\n",
-               tokenizer.Status().error, tokenizer.Status().pos);
-        return;
-      case CBORTokenTag::DONE:
-        fprintf(stderr, "DONE\n");
-        return;
-      case CBORTokenTag::TRUE_VALUE:
-        fprintf(stderr, "TRUE_VALUE\n");
-        break;
-      case CBORTokenTag::FALSE_VALUE:
-        fprintf(stderr, "FALSE_VALUE\n");
-        break;
-      case CBORTokenTag::NULL_VALUE:
-        fprintf(stderr, "NULL_VALUE\n");
-        break;
-      case CBORTokenTag::INT32:
-        fprintf(stderr, "INT32 [%d]\n", tokenizer.GetInt32());
-        break;
-      case CBORTokenTag::DOUBLE:
-        fprintf(stderr, "DOUBLE [%lf]\n", tokenizer.GetDouble());
-        break;
-      case CBORTokenTag::STRING8: {
-        span<uint8_t> v = tokenizer.GetString8();
-        std::string t(v.begin(), v.end());
-        fprintf(stderr, "STRING8 [%s]\n", t.c_str());
-        break;
-      }
-      case CBORTokenTag::STRING16: {
-        span<uint8_t> v = tokenizer.GetString16WireRep();
-        std::string t(v.begin(), v.end());
-        fprintf(stderr, "STRING16 [%s]\n", t.c_str());
-        break;
-      }
-      case CBORTokenTag::BINARY: {
-        span<uint8_t> v = tokenizer.GetBinary();
-        std::string t(v.begin(), v.end());
-        fprintf(stderr, "BINARY [%s]\n", t.c_str());
-        break;
-      }
-      case CBORTokenTag::MAP_START:
-        fprintf(stderr, "MAP_START\n");
-        indent += "  ";
-        break;
-      case CBORTokenTag::ARRAY_START:
-        fprintf(stderr, "ARRAY_START\n");
-        indent += "  ";
-        break;
-      case CBORTokenTag::STOP:
-        fprintf(stderr, "STOP\n");
-        indent.erase(0, 2);
-        break;
-      case CBORTokenTag::ENVELOPE:
-        fprintf(stderr, "ENVELOPE\n");
-        tokenizer.EnterEnvelope();
-        continue;
-    }
-    tokenizer.Next();
-  }
-}
-#endif
-
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/cbor.h b/third_party/inspector_protocol/encoding/cbor.h
deleted file mode 100644
index 2785f633..0000000
--- a/third_party/inspector_protocol/encoding/cbor.h
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_CBOR_H_
-#define INSPECTOR_PROTOCOL_ENCODING_CBOR_H_
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-#include "cbor_internals.h"
-#include "json_parser_handler.h"
-#include "span.h"
-#include "status.h"
-
-namespace inspector_protocol {
-
-namespace cbor {
-
-// The major types from RFC 7049 Section 2.1.
-enum class MajorType {
-  UNSIGNED = 0,
-  NEGATIVE = 1,
-  BYTE_STRING = 2,
-  STRING = 3,
-  ARRAY = 4,
-  MAP = 5,
-  TAG = 6,
-  SIMPLE_VALUE = 7
-};
-
-// Indicates the number of bits the "initial byte" needs to be shifted to the
-// right after applying |kMajorTypeMask| to produce the major type in the
-// lowermost bits.
-static constexpr uint8_t kMajorTypeBitShift = 5u;
-// Mask selecting the low-order 5 bits of the "initial byte", which is where
-// the additional information is encoded.
-static constexpr uint8_t kAdditionalInformationMask = 0x1f;
-// Mask selecting the high-order 3 bits of the "initial byte", which indicates
-// the major type of the encoded value.
-static constexpr uint8_t kMajorTypeMask = 0xe0;
-// Indicates the integer is in the following byte.
-static constexpr uint8_t kAdditionalInformation1Byte = 24u;
-// Indicates the integer is in the next 2 bytes.
-static constexpr uint8_t kAdditionalInformation2Bytes = 25u;
-// Indicates the integer is in the next 4 bytes.
-static constexpr uint8_t kAdditionalInformation4Bytes = 26u;
-// Indicates the integer is in the next 8 bytes.
-static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
-
-// Encodes the initial byte, consisting of the |type| in the first 3 bits
-// followed by 5 bits of |additional_info|.
-constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
-  return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
-         (additional_info & kAdditionalInformationMask);
-}
-
-// TAG 24 indicates that what follows is a byte string which is
-// encoded in CBOR format. We use this as a wrapper for
-// maps and arrays, allowing us to skip them, because the
-// byte string carries its size (byte length).
-// https://tools.ietf.org/html/rfc7049#section-2.4.4.1
-static constexpr uint8_t kInitialByteForEnvelope =
-    EncodeInitialByte(MajorType::TAG, 24);
-// The initial byte for a byte string with at most 2^32 bytes
-// of payload. This is used for envelope encoding, even if
-// the byte string is shorter.
-static constexpr uint8_t kInitialByteFor32BitLengthByteString =
-    EncodeInitialByte(MajorType::BYTE_STRING, 26);
-
-// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
-// info = 31.
-static constexpr uint8_t kInitialByteIndefiniteLengthArray =
-    EncodeInitialByte(MajorType::ARRAY, 31);
-static constexpr uint8_t kInitialByteIndefiniteLengthMap =
-    EncodeInitialByte(MajorType::MAP, 31);
-// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
-// length maps / arrays.
-static constexpr uint8_t kStopByte =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
-
-}  // namespace cbor
-
-// The binary encoding for the inspector protocol follows the CBOR specification
-// (RFC 7049). Additional constraints:
-// - Only indefinite length maps and arrays are supported.
-// - Maps and arrays are wrapped with an envelope, that is, a
-//   CBOR tag with value 24 followed by a byte string specifying
-//   the byte length of the enclosed map / array. The byte string
-//   must use a 32 bit wide length.
-// - At the top level, a message must be an indefinite length map
-//   wrapped by an envelope.
-// - Maximal size for messages is 2^32 (4 GB).
-// - For scalars, we support only the int32_t range, encoded as
-//   UNSIGNED/NEGATIVE (major types 0 / 1).
-// - UTF16 strings, including with unbalanced surrogate pairs, are encoded
-//   as CBOR BYTE_STRING (major type 2). For such strings, the number of
-//   bytes encoded must be even.
-// - UTF8 strings (major type 3) are supported.
-// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not
-//   as UTF16 strings.
-// - Arbitrary byte arrays, in the inspector protocol called 'binary',
-//   are encoded as BYTE_STRING (major type 2), prefixed with a byte
-//   indicating base64 when rendered as JSON.
-
-// Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE|
-// (major type 1) iff < 0.
-void EncodeInt32(int32_t value, std::vector<uint8_t>* out);
-
-// Encodes a UTF16 string as a BYTE_STRING (major type 2). Each utf16
-// character in |in| is emitted with most significant byte first,
-// appending to |out|.
-void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out);
-
-// Encodes a UTF8 string |in| as STRING (major type 3).
-void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out);
-
-// Encodes the given |latin1| string as STRING8.
-// If any non-ASCII character is present, it will be represented
-// as a 2 byte UTF8 sequence.
-void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out);
-
-// Encodes the given |utf16| string as STRING8 if it's entirely US-ASCII.
-// Otherwise, encodes as STRING16.
-void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out);
-
-// Encodes arbitrary binary data in |in| as a BYTE_STRING (major type 2) with
-// definitive length, prefixed with tag 22 indicating expected conversion to
-// base64 (see RFC 7049, Table 3 and Section 2.4.4.2).
-void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out);
-
-// Encodes / decodes a double as Major type 7 (SIMPLE_VALUE),
-// with additional info = 27, followed by 8 bytes in big endian.
-void EncodeDouble(double value, std::vector<uint8_t>* out);
-
-// Some constants for CBOR tokens that only take a single byte on the wire.
-uint8_t EncodeTrue();
-uint8_t EncodeFalse();
-uint8_t EncodeNull();
-uint8_t EncodeIndefiniteLengthArrayStart();
-uint8_t EncodeIndefiniteLengthMapStart();
-uint8_t EncodeStop();
-
-// An envelope indicates the byte length of a wrapped item.
-// We use this for maps and array, which allows the decoder
-// to skip such (nested) values whole sale.
-// It's implemented as a CBOR tag (major type 6) with additional
-// info = 24, followed by a byte string with a 32 bit length value;
-// so the maximal structure that we can wrap is 2^32 bits long.
-// See also: https://tools.ietf.org/html/rfc7049#section-2.4.4.1
-class EnvelopeEncoder {
- public:
-  // Emits the envelope start bytes and records the position for the
-  // byte size in |byte_size_pos_|. Also emits empty bytes for the
-  // byte sisze so that encoding can continue.
-  void EncodeStart(std::vector<uint8_t>* out);
-  // This records the current size in |out| at position byte_size_pos_.
-  // Returns true iff successful.
-  bool EncodeStop(std::vector<uint8_t>* out);
-
- private:
-  std::size_t byte_size_pos_ = 0;
-};
-
-// This can be used to convert from JSON to CBOR, by passing the
-// return value to the routines in json_parser.h.  The handler will encode into
-// |out|, and iff an error occurs it will set |status| to an error and clear
-// |out|. Otherwise, |status.ok()| will be |true|.
-std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder(
-    std::vector<uint8_t>* out, Status* status);
-
-// Parses a CBOR encoded message from |bytes|, sending JSON events to
-// |json_out|. If an error occurs, sends |out->HandleError|, and parsing stops.
-// The client is responsible for discarding the already received information in
-// that case.
-void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out);
-
-// Tags for the tokens within a CBOR message that CBORStream understands.
-// Note that this is not the same terminology as the CBOR spec (RFC 7049),
-// but rather, our adaptation. For instance, we lump unsigned and signed
-// major type into INT32 here (and disallow values outside the int32_t range).
-enum class CBORTokenTag {
-  // Encountered an error in the structure of the message. Consult
-  // status() for details.
-  ERROR_VALUE,
-  // Booleans and NULL.
-  TRUE_VALUE,
-  FALSE_VALUE,
-  NULL_VALUE,
-  // An int32_t (signed 32 bit integer).
-  INT32,
-  // A double (64 bit floating point).
-  DOUBLE,
-  // A UTF8 string.
-  STRING8,
-  // A UTF16 string.
-  STRING16,
-  // A binary string.
-  BINARY,
-  // Starts an indefinite length map; after the map start we expect
-  // alternating keys and values, followed by STOP.
-  MAP_START,
-  // Starts an indefinite length array; after the array start we
-  // expect values, followed by STOP.
-  ARRAY_START,
-  // Ends a map or an array.
-  STOP,
-  // An envelope indicator, wrapping a map or array.
-  // Internally this carries the byte length of the wrapped
-  // map or array. While CBORTokenizer::Next() will read / skip the entire
-  // envelope, CBORTokenizer::EnterEnvelope() reads the tokens
-  // inside of it.
-  ENVELOPE,
-  // We've reached the end there is nothing else to read.
-  DONE,
-};
-
-// CBORTokenizer segments a CBOR message, presenting the tokens therein as
-// numbers, strings, etc. This is not a complete CBOR parser, but makes it much
-// easier to implement one (e.g. ParseCBOR, above). It can also be used to parse
-// messages partially.
-class CBORTokenizer {
- public:
-  explicit CBORTokenizer(span<uint8_t> bytes);
-  ~CBORTokenizer();
-
-  // Identifies the current token that we're looking at,
-  // or ERROR_VALUE (in which ase ::Status() has details)
-  // or DONE (if we're past the last token).
-  CBORTokenTag TokenTag() const;
-
-  // Advances to the next token.
-  void Next();
-  // Can only be called if TokenTag() == CBORTokenTag::ENVELOPE.
-  // While Next() would skip past the entire envelope / what it's
-  // wrapping, EnterEnvelope positions the cursor inside of the envelope,
-  // letting the client explore the nested structure.
-  void EnterEnvelope();
-
-  // If TokenTag() is CBORTokenTag::ERROR_VALUE, then Status().error describes
-  // the error more precisely; otherwise it'll be set to Error::OK.
-  // In either case, Status().pos is the current position.
-  struct Status Status() const;
-
-  // The following methods retrieve the token values. They can only
-  // be called if TokenTag() matches.
-
-  // To be called only if ::TokenTag() == CBORTokenTag::INT32.
-  int32_t GetInt32() const;
-
-  // To be called only if ::TokenTag() == CBORTokenTag::DOUBLE.
-  double GetDouble() const;
-
-  // To be called only if ::TokenTag() == CBORTokenTag::STRING8.
-  span<uint8_t> GetString8() const;
-
-  // Wire representation for STRING16 is low byte first (little endian).
-  // To be called only if ::TokenTag() == CBORTokenTag::STRING16.
-  span<uint8_t> GetString16WireRep() const;
-
-  // To be called only if ::TokenTag() == CBORTokenTag::BINARY.
-  span<uint8_t> GetBinary() const;
-
- private:
-  void ReadNextToken(bool enter_envelope);
-  void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length);
-  void SetError(Error error);
-
-  span<uint8_t> bytes_;
-  CBORTokenTag token_tag_;
-  struct Status status_;
-  std::ptrdiff_t token_byte_length_;
-  cbor::MajorType token_start_type_;
-  uint64_t token_start_internal_value_;
-};
-
-void DumpCBOR(span<uint8_t> cbor);
-
-}  // namespace inspector_protocol
-#endif  // INSPECTOR_PROTOCOL_ENCODING_CBOR_H_
diff --git a/third_party/inspector_protocol/encoding/cbor_internals.h b/third_party/inspector_protocol/encoding/cbor_internals.h
deleted file mode 100644
index e2621d89..0000000
--- a/third_party/inspector_protocol/encoding/cbor_internals.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_CBOR_INTERNALS_H_
-#define INSPECTOR_PROTOCOL_ENCODING_CBOR_INTERNALS_H_
-
-#include <cstdint>
-#include <vector>
-#include "span.h"
-#include "status.h"
-
-// These internals are exposed for testing and implementing cbor.h.
-// Never directly depend on them from other production code.
-namespace inspector_protocol {
-namespace cbor {
-enum class MajorType;
-}
-
-namespace cbor_internals {
-
-// Reads the start of a token with definitive size from |bytes|.
-// |type| is the major type as specified in RFC 7049 Section 2.1.
-// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
-// (e.g. for BYTE_STRING).
-// If successful, returns the number of bytes read. Otherwise returns -1.
-int8_t ReadTokenStart(span<uint8_t> bytes,
-                      cbor::MajorType* type,
-                      uint64_t* value);
-
-// Writes the start of a token with |type|. The |value| may indicate the size,
-// or it may be the payload if the value is an unsigned integer.
-void WriteTokenStart(cbor::MajorType type,
-                     uint64_t value,
-                     std::vector<uint8_t>* encoded);
-}  // namespace cbor_internals
-}  // namespace inspector_protocol
-
-#endif  // INSPECTOR_PROTOCOL_ENCODING_CBOR_H_
diff --git a/third_party/inspector_protocol/encoding/cbor_test.cc b/third_party/inspector_protocol/encoding/cbor_test.cc
deleted file mode 100644
index 9f6201f..0000000
--- a/third_party/inspector_protocol/encoding/cbor_test.cc
+++ /dev/null
@@ -1,994 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cbor.h"
-
-#include <array>
-#include <cmath>
-#include <string>
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "json_parser.h"
-#include "json_std_string_writer.h"
-#include "linux_dev_platform.h"
-
-using testing::ElementsAreArray;
-
-namespace inspector_protocol {
-
-using cbor::MajorType;
-
-//
-// EncodeInt32 / CBORTokenTag::INT32
-//
-TEST(EncodeDecodeInt32Test, Roundtrips23) {
-  // This roundtrips the int32_t value 23 through the pair of EncodeInt32 /
-  // CBORTokenizer; this is interesting since 23 is encoded as a single byte.
-  std::vector<uint8_t> encoded;
-  EncodeInt32(23, &encoded);
-  // first three bits: major type = 0; remaining five bits: additional info =
-  // value 23.
-  EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{23}}));
-
-  // Reverse direction: decode with CBORTokenizer.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
-  EXPECT_EQ(23, tokenizer.GetInt32());
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeInt32Test, RoundtripsUint8) {
-  // This roundtrips the int32_t value 42 through the pair of EncodeInt32 /
-  // CBORTokenizer. This is different from Roundtrip23 because 42 is encoded
-  // in an extra byte after the initial one.
-  std::vector<uint8_t> encoded;
-  EncodeInt32(42, &encoded);
-  // first three bits: major type = 0;
-  // remaining five bits: additional info = 24, indicating payload is uint8.
-  EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 2>{{24, 42}}));
-
-  // Reverse direction: decode with CBORTokenizer.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
-  EXPECT_EQ(42, tokenizer.GetInt32());
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeInt32Test, RoundtripsUint16) {
-  // 500 is encoded as a uint16 after the initial byte.
-  std::vector<uint8_t> encoded;
-  EncodeInt32(500, &encoded);
-  // 1 for initial byte, 2 for uint16.
-  EXPECT_EQ(static_cast<std::size_t>(3), encoded.size());
-  // first three bits: major type = 0;
-  // remaining five bits: additional info = 25, indicating payload is uint16.
-  EXPECT_EQ(25, encoded[0]);
-  EXPECT_EQ(0x01, encoded[1]);
-  EXPECT_EQ(0xf4, encoded[2]);
-
-  // Reverse direction: decode with CBORTokenizer.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
-  EXPECT_EQ(500, tokenizer.GetInt32());
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) {
-  // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte.
-  std::vector<uint8_t> encoded;
-  EncodeInt32(std::numeric_limits<int32_t>::max(), &encoded);
-  // 1 for initial byte, 4 for the uint32.
-  // first three bits: major type = 0;
-  // remaining five bits: additional info = 26, indicating payload is uint32.
-  EXPECT_THAT(
-      encoded,
-      ElementsAreArray(std::array<uint8_t, 5>{{26, 0x7f, 0xff, 0xff, 0xff}}));
-
-  // Reverse direction: decode with CBORTokenizer.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
-  EXPECT_EQ(std::numeric_limits<int32_t>::max(), tokenizer.GetInt32());
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeInt32Test, CantRoundtripUint32) {
-  // 0xdeadbeef is a value which does not fit below
-  // std::numerical_limits<int32_t>::max(), so we can't encode
-  // it with EncodeInt32. However, CBOR does support this, so we
-  // encode it here manually with the internal routine, just to observe
-  // that it's considered an invalid int32 by CBORTokenizer.
-  std::vector<uint8_t> encoded;
-  cbor_internals::WriteTokenStart(MajorType::UNSIGNED, 0xdeadbeef, &encoded);
-  // 1 for initial byte, 4 for the uint32.
-  // first three bits: major type = 0;
-  // remaining five bits: additional info = 26, indicating payload is uint32.
-  EXPECT_THAT(
-      encoded,
-      ElementsAreArray(std::array<uint8_t, 5>{{26, 0xde, 0xad, 0xbe, 0xef}}));
-
-  // Now try to decode; we treat this as an invalid INT32.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  // 0xdeadbeef is > std::numerical_limits<int32_t>::max().
-  EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
-  EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error);
-}
-
-TEST(EncodeDecodeInt32Test, DecodeErrorCases) {
-  struct TestCase {
-    std::vector<uint8_t> data;
-    std::string msg;
-  };
-  std::vector<TestCase> tests{
-      {TestCase{
-           {24},
-           "additional info = 24 would require 1 byte of payload (but it's 0)"},
-       TestCase{{27, 0xaa, 0xbb, 0xcc},
-                "additional info = 27 would require 8 bytes of payload (but "
-                "it's 3)"},
-       TestCase{{29}, "additional info = 29 isn't recognized"}}};
-
-  for (const TestCase& test : tests) {
-    SCOPED_TRACE(test.msg);
-    span<uint8_t> encoded_bytes(&test.data[0], test.data.size());
-    CBORTokenizer tokenizer(
-        span<uint8_t>(&encoded_bytes[0], encoded_bytes.size()));
-    EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
-    EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error);
-  }
-}
-
-TEST(EncodeDecodeInt32Test, RoundtripsMinus24) {
-  // This roundtrips the int32_t value -24 through the pair of EncodeInt32 /
-  // CBORTokenizer; this is interesting since -24 is encoded as
-  // a single byte as NEGATIVE, and it tests the specific encoding
-  // (note how for unsigned the single byte covers values up to 23).
-  // Additional examples are covered in RoundtripsAdditionalExamples.
-  std::vector<uint8_t> encoded;
-  EncodeInt32(-24, &encoded);
-  // first three bits: major type = 1; remaining five bits: additional info =
-  // value 23.
-  EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{1 << 5 | 23}}));
-
-  // Reverse direction: decode with CBORTokenizer.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
-  EXPECT_EQ(-24, tokenizer.GetInt32());
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeInt32Test, RoundtripsAdditionalNegativeExamples) {
-  std::vector<int32_t> examples = {-1,
-                                   -10,
-                                   -24,
-                                   -25,
-                                   -300,
-                                   -30000,
-                                   -300 * 1000,
-                                   -1000 * 1000,
-                                   -1000 * 1000 * 1000,
-                                   std::numeric_limits<int32_t>::min()};
-  for (int32_t example : examples) {
-    SCOPED_TRACE(base::StringPrintf("example %d", example));
-    std::vector<uint8_t> encoded;
-    EncodeInt32(example, &encoded);
-    CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-    EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
-    EXPECT_EQ(example, tokenizer.GetInt32());
-    tokenizer.Next();
-    EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-  }
-}
-
-//
-// EncodeString16 / CBORTokenTag::STRING16
-//
-TEST(EncodeDecodeString16Test, RoundtripsEmpty) {
-  // This roundtrips the empty utf16 string through the pair of EncodeString16 /
-  // CBORTokenizer.
-  std::vector<uint8_t> encoded;
-  EncodeString16(span<uint16_t>(), &encoded);
-  EXPECT_EQ(static_cast<std::size_t>(1), encoded.size());
-  // first three bits: major type = 2; remaining five bits: additional info =
-  // size 0.
-  EXPECT_EQ(2 << 5, encoded[0]);
-
-  // Reverse direction: decode with CBORTokenizer.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
-  span<uint8_t> decoded_string16_wirerep = tokenizer.GetString16WireRep();
-  EXPECT_TRUE(decoded_string16_wirerep.empty());
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-// On the wire, we STRING16 is encoded as little endian (least
-// significant byte first). The host may or may not be little endian,
-// so this routine follows the advice in
-// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html.
-std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) {
-  assert((in.size() & 1) == 0);  // must be even number of bytes.
-  std::vector<uint16_t> host_out;
-  for (std::ptrdiff_t ii = 0; ii < in.size(); ii += 2)
-    host_out.push_back(in[ii + 1] << 8 | in[ii]);
-  return host_out;
-}
-
-TEST(EncodeDecodeString16Test, RoundtripsHelloWorld) {
-  // This roundtrips the hello world message which is given here in utf16
-  // characters. 0xd83c, 0xdf0e: UTF16 encoding for the "Earth Globe Americas"
-  // character, 🌎.
-  std::array<uint16_t, 10> msg{
-      {'H', 'e', 'l', 'l', 'o', ',', ' ', 0xd83c, 0xdf0e, '.'}};
-  std::vector<uint8_t> encoded;
-  EncodeString16(span<uint16_t>(msg.data(), msg.size()), &encoded);
-  // This will be encoded as BYTE_STRING of length 20, so the 20 is encoded in
-  // the additional info part of the initial byte. Payload is two bytes for each
-  // UTF16 character.
-  uint8_t initial_byte = /*major type=*/2 << 5 | /*additional info=*/20;
-  std::array<uint8_t, 21> encoded_expected = {
-      {initial_byte, 'H', 0,   'e', 0,    'l',  0,    'l',  0,   'o', 0,
-       ',',          0,   ' ', 0,   0x3c, 0xd8, 0x0e, 0xdf, '.', 0}};
-  EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
-
-  // Now decode to complete the roundtrip.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
-  std::vector<uint16_t> decoded =
-      String16WireRepToHost(tokenizer.GetString16WireRep());
-  EXPECT_THAT(decoded, ElementsAreArray(msg));
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-
-  // For bonus points, we look at the decoded message in UTF8 as well so we can
-  // easily see it on the terminal screen.
-  std::string utf8_decoded =
-      base::UTF16ToUTF8(base::StringPiece16(decoded.data(), decoded.size()));
-  EXPECT_EQ("Hello, 🌎.", utf8_decoded);
-}
-
-TEST(EncodeDecodeString16Test, Roundtrips500) {
-  // We roundtrip a message that has 250 16 bit values. Each of these are just
-  // set to their index. 250 is interesting because the cbor spec uses a
-  // BYTE_STRING of length 500 for one of their examples of how to encode the
-  // start of it (section 2.1) so it's easy for us to look at the first three
-  // bytes closely.
-  std::vector<uint16_t> two_fifty;
-  for (uint16_t ii = 0; ii < 250; ++ii) two_fifty.push_back(ii);
-  std::vector<uint8_t> encoded;
-  EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded);
-  EXPECT_EQ(static_cast<std::size_t>(3 + 250 * 2), encoded.size());
-  // Now check the first three bytes:
-  // Major type: 2 (BYTE_STRING)
-  // Additional information: 25, indicating size is represented by 2 bytes.
-  // Bytes 1 and 2 encode 500 (0x01f4).
-  EXPECT_EQ(2 << 5 | 25, encoded[0]);
-  EXPECT_EQ(0x01, encoded[1]);
-  EXPECT_EQ(0xf4, encoded[2]);
-
-  // Now decode to complete the roundtrip.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
-  std::vector<uint16_t> decoded =
-      String16WireRepToHost(tokenizer.GetString16WireRep());
-  EXPECT_THAT(decoded, ElementsAreArray(two_fifty));
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeString16Test, ErrorCases) {
-  struct TestCase {
-    std::vector<uint8_t> data;
-    std::string msg;
-  };
-  std::vector<TestCase> tests{
-      {TestCase{{2 << 5 | 1, 'a'},
-                "length must be divisible by 2 (but it's 1)"},
-       TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"}}};
-  for (const TestCase& test : tests) {
-    SCOPED_TRACE(test.msg);
-    CBORTokenizer tokenizer(span<uint8_t>(&test.data[0], test.data.size()));
-    EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
-    EXPECT_EQ(Error::CBOR_INVALID_STRING16, tokenizer.Status().error);
-  }
-}
-
-//
-// EncodeString8 / CBORTokenTag::STRING8
-//
-TEST(EncodeDecodeString8Test, RoundtripsHelloWorld) {
-  // This roundtrips the hello world message which is given here in utf8
-  // characters. 🌎 is a four byte utf8 character.
-  std::string utf8_msg = "Hello, 🌎.";
-  std::vector<uint8_t> msg(utf8_msg.begin(), utf8_msg.end());
-  std::vector<uint8_t> encoded;
-  EncodeString8(span<uint8_t>(msg.data(), msg.size()), &encoded);
-  // This will be encoded as STRING of length 12, so the 12 is encoded in
-  // the additional info part of the initial byte. Payload is one byte per
-  // utf8 byte.
-  uint8_t initial_byte = /*major type=*/3 << 5 | /*additional info=*/12;
-  std::array<uint8_t, 13> encoded_expected = {{initial_byte, 'H', 'e', 'l', 'l',
-                                               'o', ',', ' ', 0xF0, 0x9f, 0x8c,
-                                               0x8e, '.'}};
-  EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
-
-  // Now decode to complete the roundtrip.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
-  std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
-                               tokenizer.GetString8().end());
-  EXPECT_THAT(decoded, ElementsAreArray(msg));
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) {
-  std::vector<std::pair<std::string, std::string>> examples = {
-      {"Hello, world.", "Hello, world."},
-      {"Above: \xDC"
-       "ber",
-       "Above: Über"},
-      {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF",
-       "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}};
-
-  for (const auto& example : examples) {
-    const std::string& latin1 = example.first;
-    const std::string& expected_utf8 = example.second;
-    std::vector<uint8_t> encoded;
-    EncodeFromLatin1(
-        span<uint8_t>(reinterpret_cast<const uint8_t*>(latin1.data()),
-                      latin1.size()),
-        &encoded);
-    CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-    EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
-    std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
-                                 tokenizer.GetString8().end());
-    std::string decoded_str(decoded.begin(), decoded.end());
-    EXPECT_THAT(decoded_str, testing::Eq(expected_utf8));
-  }
-}
-
-TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) {
-  std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'};
-  std::vector<uint8_t> encoded;
-  EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded);
-
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
-  std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
-                               tokenizer.GetString8().end());
-  std::string decoded_str(decoded.begin(), decoded.end());
-  EXPECT_THAT(decoded_str, testing::Eq("easy"));
-}
-
-TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) {
-  // Since this message contains non-ASCII characters, the routine is
-  // forced to encode as UTF16. We see this below by checking that the
-  // token tag is STRING16.
-  std::vector<uint16_t> msg = {'H', 'e', 'l',    'l',    'o',
-                               ',', ' ', 0xd83c, 0xdf0e, '.'};
-  std::vector<uint8_t> encoded;
-  EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded);
-
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
-  std::vector<uint16_t> decoded =
-      String16WireRepToHost(tokenizer.GetString16WireRep());
-  std::string utf8_decoded =
-      base::UTF16ToUTF8(base::StringPiece16(decoded.data(), decoded.size()));
-  EXPECT_EQ("Hello, 🌎.", utf8_decoded);
-}
-
-//
-// EncodeBinary / CBORTokenTag::BINARY
-//
-TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) {
-  std::vector<uint8_t> binary = {'H', 'e', 'l', 'l', 'o', ',', ' ',
-                                 'w', 'o', 'r', 'l', 'd', '.'};
-  std::vector<uint8_t> encoded;
-  EncodeBinary(span<uint8_t>(binary.data(), binary.size()), &encoded);
-  // So, on the wire we see that the binary blob travels unmodified.
-  EXPECT_THAT(
-      encoded,
-      ElementsAreArray(std::array<uint8_t, 15>{
-          {(6 << 5 | 22),  // tag 22 indicating base64 interpretation in JSON
-           (2 << 5 | 13),  // BYTE_STRING (type 2) of length 13
-           'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}}));
-  std::vector<uint8_t> decoded;
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag());
-  EXPECT_EQ(0, int(tokenizer.Status().error));
-  decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(),
-                                 tokenizer.GetBinary().end());
-  EXPECT_THAT(decoded, ElementsAreArray(binary));
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-//
-// EncodeDouble / CBORTokenTag::DOUBLE
-//
-TEST(EncodeDecodeDoubleTest, RoundtripsWikipediaExample) {
-  // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
-  // provides the example of a hex representation 3FD5 5555 5555 5555, which
-  // approximates 1/3.
-
-  const double kOriginalValue = 1.0 / 3;
-  std::vector<uint8_t> encoded;
-  EncodeDouble(kOriginalValue, &encoded);
-  // first three bits: major type = 7; remaining five bits: additional info =
-  // value 27. This is followed by 8 bytes of payload (which match Wikipedia).
-  EXPECT_THAT(
-      encoded,
-      ElementsAreArray(std::array<uint8_t, 9>{
-          {7 << 5 | 27, 0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}}));
-
-  // Reverse direction: decode and compare with original value.
-  CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-  EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
-  EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(kOriginalValue));
-  tokenizer.Next();
-  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-}
-
-TEST(EncodeDecodeDoubleTest, RoundtripsAdditionalExamples) {
-  std::vector<double> examples = {0.0,
-                                  1.0,
-                                  -1.0,
-                                  3.1415,
-                                  std::numeric_limits<double>::min(),
-                                  std::numeric_limits<double>::max(),
-                                  std::numeric_limits<double>::infinity(),
-                                  std::numeric_limits<double>::quiet_NaN()};
-  for (double example : examples) {
-    SCOPED_TRACE(base::StringPrintf("example %lf", example));
-    std::vector<uint8_t> encoded;
-    EncodeDouble(example, &encoded);
-    span<uint8_t> encoded_bytes(&encoded[0], encoded.size());
-    CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size()));
-    EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
-    if (std::isnan(example))
-      EXPECT_TRUE(std::isnan(tokenizer.GetDouble()));
-    else
-      EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(example));
-    tokenizer.Next();
-    EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
-  }
-}
-
-//
-// NewJSONToCBOREncoder
-//
-void EncodeUTF8ForTest(const std::string& key, std::vector<uint8_t>* out) {
-  EncodeString8(
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(key.data()), key.size()),
-      out);
-}
-
-TEST(JSONToCBOREncoderTest, SevenBitStrings) {
-  // When a string can be represented as 7 bit ASCII, the encoder will use the
-  // STRING (major Type 3) type, so the actual characters end up as bytes on the
-  // wire.
-  std::vector<uint8_t> encoded;
-  Status status;
-  std::unique_ptr<JSONParserHandler> encoder =
-      NewJSONToCBOREncoder(&encoded, &status);
-  std::vector<uint16_t> utf16 = {'f', 'o', 'o'};
-  encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size()));
-  EXPECT_EQ(Error::OK, status.error);
-  // Here we assert that indeed, seven bit strings are represented as
-  // bytes on the wire, "foo" is just "foo".
-  EXPECT_THAT(encoded,
-              ElementsAreArray(std::array<uint8_t, 4>{
-                  {/*major type 3*/ 3 << 5 | /*length*/ 3, 'f', 'o', 'o'}}));
-}
-
-TEST(JsonCborRoundtrip, EncodingDecoding) {
-  // Hits all the cases except binary and error in JSONParserHandler, first
-  // parsing a JSON message into CBOR, then parsing it back from CBOR into JSON.
-  std::string json =
-      "{"
-      "\"string\":\"Hello, \\ud83c\\udf0e.\","
-      "\"double\":3.1415,"
-      "\"int\":1,"
-      "\"negative int\":-1,"
-      "\"bool\":true,"
-      "\"null\":null,"
-      "\"array\":[1,2,3]"
-      "}";
-  std::vector<uint8_t> encoded;
-  Status status;
-  std::unique_ptr<JSONParserHandler> encoder =
-      NewJSONToCBOREncoder(&encoded, &status);
-  span<uint8_t> ascii_in(reinterpret_cast<const uint8_t*>(json.data()),
-                         json.size());
-  ParseJSONChars(GetLinuxDevPlatform(), ascii_in, encoder.get());
-  std::vector<uint8_t> expected = {
-      0xd8,            // envelope
-      0x5a,            // byte string with 32 bit length
-      0,    0, 0, 94,  // length is 94 bytes
-  };
-  expected.push_back(0xbf);  // indef length map start
-  EncodeUTF8ForTest("string", &expected);
-  // This is followed by the encoded string for "Hello, 🌎."
-  // So, it's the same bytes that we tested above in
-  // EncodeDecodeString16Test.RoundtripsHelloWorld.
-  expected.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
-  for (uint8_t ch : std::array<uint8_t, 20>{
-           {'H', 0, 'e', 0, 'l',  0,    'l',  0,    'o', 0,
-            ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
-    expected.push_back(ch);
-  EncodeUTF8ForTest("double", &expected);
-  EncodeDouble(3.1415, &expected);
-  EncodeUTF8ForTest("int", &expected);
-  EncodeInt32(1, &expected);
-  EncodeUTF8ForTest("negative int", &expected);
-  EncodeInt32(-1, &expected);
-  EncodeUTF8ForTest("bool", &expected);
-  expected.push_back(7 << 5 | 21);  // RFC 7049 Section 2.3, Table 2: true
-  EncodeUTF8ForTest("null", &expected);
-  expected.push_back(7 << 5 | 22);  // RFC 7049 Section 2.3, Table 2: null
-  EncodeUTF8ForTest("array", &expected);
-  expected.push_back(0xd8);  // envelope
-  expected.push_back(0x5a);  // byte string with 32 bit length
-  // the length is 5 bytes (that's up to end indef length array below).
-  for (uint8_t ch : std::array<uint8_t, 4>{{0, 0, 0, 5}})
-    expected.push_back(ch);
-  expected.push_back(0x9f);  // RFC 7049 Section 2.2.1, indef length array start
-  expected.push_back(1);     // Three UNSIGNED values (easy since Major Type 0)
-  expected.push_back(2);
-  expected.push_back(3);
-  expected.push_back(0xff);  // End indef length array
-  expected.push_back(0xff);  // End indef length map
-  EXPECT_TRUE(status.ok());
-  EXPECT_THAT(encoded, ElementsAreArray(expected));
-
-  // And now we roundtrip, decoding the message we just encoded.
-  std::string decoded;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &decoded, &status);
-  ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
-  EXPECT_EQ(Error::OK, status.error);
-  EXPECT_EQ(json, decoded);
-}
-
-TEST(JsonCborRoundtrip, MoreRoundtripExamples) {
-  std::vector<std::string> examples = {
-      // Tests that after closing a nested objects, additional key/value pairs
-      // are considered.
-      "{\"foo\":{\"bar\":1},\"baz\":2}", "{\"foo\":[1,2,3],\"baz\":2}"};
-  for (const std::string& json : examples) {
-    SCOPED_TRACE(std::string("example: ") + json);
-    std::vector<uint8_t> encoded;
-    Status status;
-    std::unique_ptr<JSONParserHandler> encoder =
-        NewJSONToCBOREncoder(&encoded, &status);
-    span<uint8_t> ascii_in(reinterpret_cast<const uint8_t*>(json.data()),
-                           json.size());
-    ParseJSONChars(GetLinuxDevPlatform(), ascii_in, encoder.get());
-    std::string decoded;
-    std::unique_ptr<JSONParserHandler> json_writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &decoded, &status);
-    ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
-    EXPECT_EQ(Error::OK, status.error);
-    EXPECT_EQ(json, decoded);
-  }
-}
-
-TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) {
-  // The JSONParserHandler::HandleBinary is a special case: The JSON parser will
-  // never call this method, because JSON does not natively support the binary
-  // type. So, we can't fully roundtrip. However, the other direction works:
-  // binary will be rendered in JSON, as a base64 string. So, we make calls to
-  // the encoder directly here, to construct a message, and one of these calls
-  // is ::HandleBinary, to which we pass a "binary" string containing "Hello,
-  // world.".
-  std::vector<uint8_t> encoded;
-  Status status;
-  std::unique_ptr<JSONParserHandler> encoder =
-      NewJSONToCBOREncoder(&encoded, &status);
-  encoder->HandleObjectBegin();
-  // Emit a key.
-  std::vector<uint16_t> key = {'f', 'o', 'o'};
-  encoder->HandleString16(span<uint16_t>(key.data(), key.size()));
-  // Emit the binary payload, an arbitrary array of bytes that happens to
-  // be the ascii message "Hello, world.".
-  encoder->HandleBinary(std::vector<uint8_t>{'H', 'e', 'l', 'l', 'o', ',', ' ',
-                                             'w', 'o', 'r', 'l', 'd', '.'});
-  encoder->HandleObjectEnd();
-  EXPECT_EQ(Error::OK, status.error);
-
-  // Now drive the json writer via the CBOR decoder.
-  std::string decoded;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &decoded, &status);
-  ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
-  EXPECT_EQ(Error::OK, status.error);
-  EXPECT_EQ(Status::npos(), status.pos);
-  // "Hello, world." in base64 is "SGVsbG8sIHdvcmxkLg==".
-  EXPECT_EQ("{\"foo\":\"SGVsbG8sIHdvcmxkLg==\"}", decoded);
-}
-
-//
-// ParseCBOR
-//
-TEST(ParseCBORTest, ParseEmptyCBORMessage) {
-  // An envelope starting with 0xd8, 0x5a, with the byte length
-  // of 2, containing a map that's empty (0xbf for map
-  // start, and 0xff for map end).
-  std::vector<uint8_t> in = {0xd8, 0x5a, 0, 0, 0, 2, 0xbf, 0xff};
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
-  EXPECT_EQ(Error::OK, status.error);
-  EXPECT_EQ("{}", out);
-}
-
-TEST(ParseCBORTest, ParseCBORHelloWorld) {
-  const uint8_t kPayloadLen = 27;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen};
-  bytes.push_back(0xbf);                       // start indef length map.
-  EncodeUTF8ForTest("msg", &bytes);            // key: msg
-  // Now write the value, the familiar "Hello, 🌎." where the globe is expressed
-  // as two utf16 chars.
-  bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
-  for (uint8_t ch : std::array<uint8_t, 20>{
-           {'H', 0, 'e', 0, 'l',  0,    'l',  0,    'o', 0,
-            ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
-    bytes.push_back(ch);
-  bytes.push_back(0xff);  // stop byte
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::OK, status.error);
-  EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out);
-}
-
-TEST(ParseCBORTest, UTF8IsSupportedInKeys) {
-  const uint8_t kPayloadLen = 11;
-  std::vector<uint8_t> bytes = {cbor::kInitialByteForEnvelope,
-                                cbor::kInitialByteFor32BitLengthByteString,
-                                0,
-                                0,
-                                0,
-                                kPayloadLen};
-  bytes.push_back(cbor::kInitialByteIndefiniteLengthMap);
-  EncodeUTF8ForTest("🌎", &bytes);  // Two UTF16 chars.
-  EncodeUTF8ForTest("☾", &bytes);  // Can be encoded as a single UTF16 char.
-  bytes.push_back(cbor::kStopByte);
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::OK, status.error);
-  EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out);
-}
-
-TEST(ParseCBORTest, NoInputError) {
-  std::vector<uint8_t> in = {};
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_NO_INPUT, status.error);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidStartByteError) {
-  // Here we test that some actual json, which usually starts with {,
-  // is not considered CBOR. CBOR messages must start with 0x5a, the
-  // envelope start byte.
-  std::string json = "{\"msg\": \"Hello, world.\"}";
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
-  constexpr uint8_t kPayloadLen = 5;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);  // A key; so value would be next.
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error);
-  EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, UnexpectedEofInArrayError) {
-  constexpr uint8_t kPayloadLen = 8;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};  // The byte for starting a map.
-  EncodeUTF8ForTest("array", &bytes);   // A key; so value would be next.
-  bytes.push_back(0x9f);  // byte for indefinite length array start.
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error);
-  EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, UnexpectedEofInMapError) {
-  constexpr uint8_t kPayloadLen = 1;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};  // The byte for starting a map.
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error);
-  EXPECT_EQ(7, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidMapKeyError) {
-  constexpr uint8_t kPayloadLen = 2;
-  std::vector<uint8_t> bytes = {0xd8,       0x5a, 0,
-                                0,          0,    kPayloadLen,  // envelope
-                                0xbf,                           // map start
-                                7 << 5 | 22};  // null (not a valid map key)
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error);
-  EXPECT_EQ(7, status.pos);
-  EXPECT_EQ("", out);
-}
-
-std::vector<uint8_t> MakeNestedCBOR(int depth) {
-  std::vector<uint8_t> bytes;
-  std::vector<EnvelopeEncoder> envelopes;
-  for (int ii = 0; ii < depth; ++ii) {
-    envelopes.emplace_back();
-    envelopes.back().EncodeStart(&bytes);
-    bytes.push_back(0xbf);  // indef length map start
-    EncodeUTF8ForTest("key", &bytes);
-  }
-  EncodeUTF8ForTest("innermost_value", &bytes);
-  for (int ii = 0; ii < depth; ++ii) {
-    bytes.push_back(0xff);  // stop byte, finishes map.
-    envelopes.back().EncodeStop(&bytes);
-    envelopes.pop_back();
-  }
-  return bytes;
-}
-
-TEST(ParseCBORTest, StackLimitExceededError) {
-  {  // Depth 3: no stack limit exceeded error and is easy to inspect.
-    std::vector<uint8_t> bytes = MakeNestedCBOR(3);
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> json_writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-    EXPECT_EQ(Error::OK, status.error);
-    EXPECT_EQ(Status::npos(), status.pos);
-    EXPECT_EQ("{\"key\":{\"key\":{\"key\":\"innermost_value\"}}}", out);
-  }
-  {  // Depth 1000: no stack limit exceeded.
-    std::vector<uint8_t> bytes = MakeNestedCBOR(1000);
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> json_writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-    EXPECT_EQ(Error::OK, status.error);
-    EXPECT_EQ(Status::npos(), status.pos);
-  }
-
-  // We just want to know the length of one opening map so we can compute
-  // where the error is encountered. So we look at a small example and find
-  // the second envelope start.
-  std::vector<uint8_t> small_example = MakeNestedCBOR(3);
-  int64_t opening_segment_size = 1;  // Start after the first envelope start.
-  while (opening_segment_size < static_cast<int64_t>(small_example.size()) &&
-         small_example[opening_segment_size] != 0xd8)
-    opening_segment_size++;
-
-  {  // Depth 1001: limit exceeded.
-    std::vector<uint8_t> bytes = MakeNestedCBOR(1001);
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> json_writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-    EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
-    EXPECT_EQ(opening_segment_size * 1001, status.pos);
-  }
-  {  // Depth 1200: still limit exceeded, and at the same pos as for 1001
-    std::vector<uint8_t> bytes = MakeNestedCBOR(1200);
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> json_writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-    EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
-    EXPECT_EQ(opening_segment_size * 1001, status.pos);
-  }
-}
-
-TEST(ParseCBORTest, UnsupportedValueError) {
-  constexpr uint8_t kPayloadLen = 6;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  int64_t error_pos = bytes.size();
-  bytes.push_back(6 << 5 | 5);  // tags aren't supported yet.
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidString16Error) {
-  constexpr uint8_t kPayloadLen = 11;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  int64_t error_pos = bytes.size();
-  // a BYTE_STRING of length 5 as value; since we interpret these as string16,
-  // it's going to be invalid as each character would need two bytes, but
-  // 5 isn't divisible by 2.
-  bytes.push_back(2 << 5 | 5);
-  for (int ii = 0; ii < 5; ++ii) bytes.push_back(' ');
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidString8Error) {
-  constexpr uint8_t kPayloadLen = 6;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  int64_t error_pos = bytes.size();
-  // a STRING of length 5 as value, but we're at the end of the bytes array
-  // so it can't be decoded successfully.
-  bytes.push_back(3 << 5 | 5);
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidBinaryError) {
-  constexpr uint8_t kPayloadLen = 9;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  int64_t error_pos = bytes.size();
-  bytes.push_back(6 << 5 | 22);  // base64 hint for JSON; indicates binary
-  bytes.push_back(2 << 5 | 10);  // BYTE_STRING (major type 2) of length 10
-  // Just two garbage bytes, not enough for the binary.
-  bytes.push_back(0x31);
-  bytes.push_back(0x23);
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidDoubleError) {
-  constexpr uint8_t kPayloadLen = 8;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  int64_t error_pos = bytes.size();
-  bytes.push_back(7 << 5 | 27);  // initial byte for double
-  // Just two garbage bytes, not enough to represent an actual double.
-  bytes.push_back(0x31);
-  bytes.push_back(0x23);
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, InvalidSignedError) {
-  constexpr uint8_t kPayloadLen = 14;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  int64_t error_pos = bytes.size();
-  // uint64_t max is a perfectly fine value to encode as CBOR unsigned,
-  // but we don't support this since we only cover the int32_t range.
-  cbor_internals::WriteTokenStart(MajorType::UNSIGNED,
-                                  std::numeric_limits<uint64_t>::max(), &bytes);
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-
-TEST(ParseCBORTest, TrailingJunk) {
-  constexpr uint8_t kPayloadLen = 35;
-  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
-                                0xbf};                             // map start
-  EncodeUTF8ForTest("key", &bytes);
-  EncodeUTF8ForTest("value", &bytes);
-  bytes.push_back(0xff);  // Up to here, it's a perfectly fine msg.
-  int64_t error_pos = bytes.size();
-  EncodeUTF8ForTest("trailing junk", &bytes);
-
-  cbor_internals::WriteTokenStart(MajorType::UNSIGNED,
-                                  std::numeric_limits<uint64_t>::max(), &bytes);
-  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> json_writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
-  EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error);
-  EXPECT_EQ(error_pos, status.pos);
-  EXPECT_EQ("", out);
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/encoding.cc b/third_party/inspector_protocol/encoding/encoding.cc
new file mode 100644
index 0000000..b02a36a
--- /dev/null
+++ b/third_party/inspector_protocol/encoding/encoding.cc
@@ -0,0 +1,1796 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "encoding.h"
+
+#include <cassert>
+#include <cstring>
+#include <limits>
+#include <stack>
+
+namespace inspector_protocol_encoding {
+namespace cbor {
+namespace {
+// Indicates the number of bits the "initial byte" needs to be shifted to the
+// right after applying |kMajorTypeMask| to produce the major type in the
+// lowermost bits.
+static constexpr uint8_t kMajorTypeBitShift = 5u;
+// Mask selecting the low-order 5 bits of the "initial byte", which is where
+// the additional information is encoded.
+static constexpr uint8_t kAdditionalInformationMask = 0x1f;
+// Mask selecting the high-order 3 bits of the "initial byte", which indicates
+// the major type of the encoded value.
+static constexpr uint8_t kMajorTypeMask = 0xe0;
+// Indicates the integer is in the following byte.
+static constexpr uint8_t kAdditionalInformation1Byte = 24u;
+// Indicates the integer is in the next 2 bytes.
+static constexpr uint8_t kAdditionalInformation2Bytes = 25u;
+// Indicates the integer is in the next 4 bytes.
+static constexpr uint8_t kAdditionalInformation4Bytes = 26u;
+// Indicates the integer is in the next 8 bytes.
+static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
+
+// Encodes the initial byte, consisting of the |type| in the first 3 bits
+// followed by 5 bits of |additional_info|.
+constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
+  return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
+         (additional_info & kAdditionalInformationMask);
+}
+
+// TAG 24 indicates that what follows is a byte string which is
+// encoded in CBOR format. We use this as a wrapper for
+// maps and arrays, allowing us to skip them, because the
+// byte string carries its size (byte length).
+// https://tools.ietf.org/html/rfc7049#section-2.4.4.1
+static constexpr uint8_t kInitialByteForEnvelope =
+    EncodeInitialByte(MajorType::TAG, 24);
+// The initial byte for a byte string with at most 2^32 bytes
+// of payload. This is used for envelope encoding, even if
+// the byte string is shorter.
+static constexpr uint8_t kInitialByteFor32BitLengthByteString =
+    EncodeInitialByte(MajorType::BYTE_STRING, 26);
+
+// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
+// info = 31.
+static constexpr uint8_t kInitialByteIndefiniteLengthArray =
+    EncodeInitialByte(MajorType::ARRAY, 31);
+static constexpr uint8_t kInitialByteIndefiniteLengthMap =
+    EncodeInitialByte(MajorType::MAP, 31);
+// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
+// length maps / arrays.
+static constexpr uint8_t kStopByte =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
+
+// See RFC 7049 Section 2.3, Table 2.
+static constexpr uint8_t kEncodedTrue =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 21);
+static constexpr uint8_t kEncodedFalse =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 20);
+static constexpr uint8_t kEncodedNull =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 22);
+static constexpr uint8_t kInitialByteForDouble =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 27);
+
+// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for
+// arbitrary binary data encoded as BYTE_STRING.
+static constexpr uint8_t kExpectedConversionToBase64Tag =
+    EncodeInitialByte(MajorType::TAG, 22);
+
+// Writes the bytes for |v| to |out|, starting with the most significant byte.
+// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+template <typename T>
+void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) {
+  for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes)
+    out->push_back(0xff & (v >> (shift_bytes * 8)));
+}
+
+// Extracts sizeof(T) bytes from |in| to extract a value of type T
+// (e.g. uint64_t, uint32_t, ...), most significant byte first.
+// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+template <typename T>
+T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
+  assert(static_cast<std::size_t>(in.size()) >= sizeof(T));
+  T result = 0;
+  for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
+    result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
+  return result;
+}
+}  // namespace
+
+namespace internals {
+// Reads the start of a token with definitive size from |bytes|.
+// |type| is the major type as specified in RFC 7049 Section 2.1.
+// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
+// (e.g. for BYTE_STRING).
+// If successful, returns the number of bytes read. Otherwise returns -1.
+int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
+  if (bytes.empty())
+    return -1;
+  uint8_t initial_byte = bytes[0];
+  *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
+
+  uint8_t additional_information = initial_byte & kAdditionalInformationMask;
+  if (additional_information < 24) {
+    // Values 0-23 are encoded directly into the additional info of the
+    // initial byte.
+    *value = additional_information;
+    return 1;
+  }
+  if (additional_information == kAdditionalInformation1Byte) {
+    // Values 24-255 are encoded with one initial byte, followed by the value.
+    if (bytes.size() < 2)
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
+    return 2;
+  }
+  if (additional_information == kAdditionalInformation2Bytes) {
+    // Values 256-65535: 1 initial byte + 2 bytes payload.
+    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t))
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
+    return 3;
+  }
+  if (additional_information == kAdditionalInformation4Bytes) {
+    // 32 bit uint: 1 initial byte + 4 bytes payload.
+    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t))
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
+    return 5;
+  }
+  if (additional_information == kAdditionalInformation8Bytes) {
+    // 64 bit uint: 1 initial byte + 8 bytes payload.
+    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t))
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
+    return 9;
+  }
+  return -1;
+}
+
+// Writes the start of a token with |type|. The |value| may indicate the size,
+// or it may be the payload if the value is an unsigned integer.
+void WriteTokenStart(MajorType type,
+                     uint64_t value,
+                     std::vector<uint8_t>* encoded) {
+  if (value < 24) {
+    // Values 0-23 are encoded directly into the additional info of the
+    // initial byte.
+    encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value));
+    return;
+  }
+  if (value <= std::numeric_limits<uint8_t>::max()) {
+    // Values 24-255 are encoded with one initial byte, followed by the value.
+    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte));
+    encoded->push_back(value);
+    return;
+  }
+  if (value <= std::numeric_limits<uint16_t>::max()) {
+    // Values 256-65535: 1 initial byte + 2 bytes payload.
+    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes));
+    WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded);
+    return;
+  }
+  if (value <= std::numeric_limits<uint32_t>::max()) {
+    // 32 bit uint: 1 initial byte + 4 bytes payload.
+    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes));
+    WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value),
+                                                 encoded);
+    return;
+  }
+  // 64 bit uint: 1 initial byte + 8 bytes payload.
+  encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes));
+  WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded);
+}
+}  // namespace internals
+
+// =============================================================================
+// Detecting CBOR content
+// =============================================================================
+
+uint8_t InitialByteForEnvelope() {
+  return kInitialByteForEnvelope;
+}
+uint8_t InitialByteFor32BitLengthByteString() {
+  return kInitialByteFor32BitLengthByteString;
+}
+bool IsCBORMessage(span<uint8_t> msg) {
+  return msg.size() >= 6 && msg[0] == InitialByteForEnvelope() &&
+         msg[1] == InitialByteFor32BitLengthByteString();
+}
+
+// =============================================================================
+// Encoding invidiual CBOR items
+// =============================================================================
+
+uint8_t EncodeTrue() {
+  return kEncodedTrue;
+}
+uint8_t EncodeFalse() {
+  return kEncodedFalse;
+}
+uint8_t EncodeNull() {
+  return kEncodedNull;
+}
+
+uint8_t EncodeIndefiniteLengthArrayStart() {
+  return kInitialByteIndefiniteLengthArray;
+}
+
+uint8_t EncodeIndefiniteLengthMapStart() {
+  return kInitialByteIndefiniteLengthMap;
+}
+
+uint8_t EncodeStop() {
+  return kStopByte;
+}
+
+void EncodeInt32(int32_t value, std::vector<uint8_t>* out) {
+  if (value >= 0) {
+    internals::WriteTokenStart(MajorType::UNSIGNED, value, out);
+  } else {
+    uint64_t representation = static_cast<uint64_t>(-(value + 1));
+    internals::WriteTokenStart(MajorType::NEGATIVE, representation, out);
+  }
+}
+
+void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) {
+  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
+  internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
+  // When emitting UTF16 characters, we always write the least significant byte
+  // first; this is because it's the native representation for X86.
+  // TODO(johannes): Implement a more efficient thing here later, e.g.
+  // casting *iff* the machine has this byte order.
+  // The wire format for UTF16 chars will probably remain the same
+  // (least significant byte first) since this way we can have
+  // golden files, unittests, etc. that port easily and universally.
+  // See also:
+  // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+  for (const uint16_t two_bytes : in) {
+    out->push_back(two_bytes);
+    out->push_back(two_bytes >> 8);
+  }
+}
+
+void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) {
+  internals::WriteTokenStart(MajorType::STRING,
+                             static_cast<uint64_t>(in.size_bytes()), out);
+  out->insert(out->end(), in.begin(), in.end());
+}
+
+void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) {
+  for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) {
+    if (latin1[ii] <= 127)
+      continue;
+    // If there's at least one non-ASCII char, convert to UTF8.
+    std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii);
+    for (; ii < latin1.size(); ++ii) {
+      if (latin1[ii] <= 127) {
+        utf8.push_back(latin1[ii]);
+      } else {
+        // 0xC0 means it's a UTF8 sequence with 2 bytes.
+        utf8.push_back((latin1[ii] >> 6) | 0xc0);
+        utf8.push_back((latin1[ii] | 0x80) & 0xbf);
+      }
+    }
+    EncodeString8(SpanFromVector(utf8), out);
+    return;
+  }
+  EncodeString8(latin1, out);
+}
+
+void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) {
+  // If there's at least one non-ASCII char, encode as STRING16 (UTF16).
+  for (uint16_t ch : utf16) {
+    if (ch <= 127)
+      continue;
+    EncodeString16(utf16, out);
+    return;
+  }
+  // It's all US-ASCII, strip out every second byte and encode as UTF8.
+  internals::WriteTokenStart(MajorType::STRING,
+                             static_cast<uint64_t>(utf16.size()), out);
+  out->insert(out->end(), utf16.begin(), utf16.end());
+}
+
+void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) {
+  out->push_back(kExpectedConversionToBase64Tag);
+  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
+  internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
+  out->insert(out->end(), in.begin(), in.end());
+}
+
+// A double is encoded with a specific initial byte
+// (kInitialByteForDouble) plus the 64 bits of payload for its value.
+constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
+
+// An envelope is encoded with a specific initial byte
+// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
+// bit wide length, plus a 32 bit length for that string.
+constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
+
+void EncodeDouble(double value, std::vector<uint8_t>* out) {
+  // The additional_info=27 indicates 64 bits for the double follow.
+  // See RFC 7049 Section 2.3, Table 1.
+  out->push_back(kInitialByteForDouble);
+  union {
+    double from_double;
+    uint64_t to_uint64;
+  } reinterpret;
+  reinterpret.from_double = value;
+  WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out);
+}
+
+// =============================================================================
+// cbor::EnvelopeEncoder - for wrapping submessages
+// =============================================================================
+
+void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) {
+  assert(byte_size_pos_ == 0);
+  out->push_back(kInitialByteForEnvelope);
+  out->push_back(kInitialByteFor32BitLengthByteString);
+  byte_size_pos_ = out->size();
+  out->resize(out->size() + sizeof(uint32_t));
+}
+
+bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) {
+  assert(byte_size_pos_ != 0);
+  // The byte size is the size of the payload, that is, all the
+  // bytes that were written past the byte size position itself.
+  uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t));
+  // We store exactly 4 bytes, so at most INT32MAX, with most significant
+  // byte first.
+  if (byte_size > std::numeric_limits<uint32_t>::max())
+    return false;
+  for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0;
+       --shift_bytes) {
+    (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8));
+  }
+  return true;
+}
+
+// =============================================================================
+// cbor::NewCBOREncoder - for encoding from a streaming parser
+// =============================================================================
+
+namespace {
+class CBOREncoder : public StreamingParserHandler {
+ public:
+  CBOREncoder(std::vector<uint8_t>* out, Status* status)
+      : out_(out), status_(status) {
+    *status_ = Status();
+  }
+
+  void HandleMapBegin() override {
+    envelopes_.emplace_back();
+    envelopes_.back().EncodeStart(out_);
+    out_->push_back(kInitialByteIndefiniteLengthMap);
+  }
+
+  void HandleMapEnd() override {
+    out_->push_back(kStopByte);
+    assert(!envelopes_.empty());
+    envelopes_.back().EncodeStop(out_);
+    envelopes_.pop_back();
+  }
+
+  void HandleArrayBegin() override {
+    envelopes_.emplace_back();
+    envelopes_.back().EncodeStart(out_);
+    out_->push_back(kInitialByteIndefiniteLengthArray);
+  }
+
+  void HandleArrayEnd() override {
+    out_->push_back(kStopByte);
+    assert(!envelopes_.empty());
+    envelopes_.back().EncodeStop(out_);
+    envelopes_.pop_back();
+  }
+
+  void HandleString8(span<uint8_t> chars) override {
+    EncodeString8(chars, out_);
+  }
+
+  void HandleString16(span<uint16_t> chars) override {
+    EncodeFromUTF16(chars, out_);
+  }
+
+  void HandleBinary(span<uint8_t> bytes) override { EncodeBinary(bytes, out_); }
+
+  void HandleDouble(double value) override { EncodeDouble(value, out_); }
+
+  void HandleInt32(int32_t value) override { EncodeInt32(value, out_); }
+
+  void HandleBool(bool value) override {
+    // See RFC 7049 Section 2.3, Table 2.
+    out_->push_back(value ? kEncodedTrue : kEncodedFalse);
+  }
+
+  void HandleNull() override {
+    // See RFC 7049 Section 2.3, Table 2.
+    out_->push_back(kEncodedNull);
+  }
+
+  void HandleError(Status error) override {
+    assert(!error.ok());
+    *status_ = error;
+    out_->clear();
+  }
+
+ private:
+  std::vector<uint8_t>* out_;
+  std::vector<EnvelopeEncoder> envelopes_;
+  Status* status_;
+};
+}  // namespace
+
+std::unique_ptr<StreamingParserHandler> NewCBOREncoder(
+    std::vector<uint8_t>* out,
+    Status* status) {
+  return std::unique_ptr<StreamingParserHandler>(new CBOREncoder(out, status));
+}
+
+// =============================================================================
+// cbor::CBORTokenizer - for parsing individual CBOR items
+// =============================================================================
+
+CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) {
+  ReadNextToken(/*enter_envelope=*/false);
+}
+CBORTokenizer::~CBORTokenizer() {}
+
+CBORTokenTag CBORTokenizer::TokenTag() const {
+  return token_tag_;
+}
+
+void CBORTokenizer::Next() {
+  if (token_tag_ == CBORTokenTag::ERROR_VALUE ||
+      token_tag_ == CBORTokenTag::DONE)
+    return;
+  ReadNextToken(/*enter_envelope=*/false);
+}
+
+void CBORTokenizer::EnterEnvelope() {
+  assert(token_tag_ == CBORTokenTag::ENVELOPE);
+  ReadNextToken(/*enter_envelope=*/true);
+}
+
+Status CBORTokenizer::Status() const {
+  return status_;
+}
+
+int32_t CBORTokenizer::GetInt32() const {
+  assert(token_tag_ == CBORTokenTag::INT32);
+  // The range checks happen in ::ReadNextToken().
+  return static_cast<uint32_t>(
+      token_start_type_ == MajorType::UNSIGNED
+          ? token_start_internal_value_
+          : -static_cast<int64_t>(token_start_internal_value_) - 1);
+}
+
+double CBORTokenizer::GetDouble() const {
+  assert(token_tag_ == CBORTokenTag::DOUBLE);
+  union {
+    uint64_t from_uint64;
+    double to_double;
+  } reinterpret;
+  reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>(
+      bytes_.subspan(status_.pos + 1));
+  return reinterpret.to_double;
+}
+
+span<uint8_t> CBORTokenizer::GetString8() const {
+  assert(token_tag_ == CBORTokenTag::STRING8);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
+}
+
+span<uint8_t> CBORTokenizer::GetString16WireRep() const {
+  assert(token_tag_ == CBORTokenTag::STRING16);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
+}
+
+span<uint8_t> CBORTokenizer::GetBinary() const {
+  assert(token_tag_ == CBORTokenTag::BINARY);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
+}
+
+span<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
+  assert(token_tag_ == CBORTokenTag::ENVELOPE);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length);
+}
+
+void CBORTokenizer::ReadNextToken(bool enter_envelope) {
+  if (enter_envelope) {
+    status_.pos += kEncodedEnvelopeHeaderSize;
+  } else {
+    status_.pos =
+        status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_;
+  }
+  status_.error = Error::OK;
+  if (status_.pos >= bytes_.size()) {
+    token_tag_ = CBORTokenTag::DONE;
+    return;
+  }
+  switch (bytes_[status_.pos]) {
+    case kStopByte:
+      SetToken(CBORTokenTag::STOP, 1);
+      return;
+    case kInitialByteIndefiniteLengthMap:
+      SetToken(CBORTokenTag::MAP_START, 1);
+      return;
+    case kInitialByteIndefiniteLengthArray:
+      SetToken(CBORTokenTag::ARRAY_START, 1);
+      return;
+    case kEncodedTrue:
+      SetToken(CBORTokenTag::TRUE_VALUE, 1);
+      return;
+    case kEncodedFalse:
+      SetToken(CBORTokenTag::FALSE_VALUE, 1);
+      return;
+    case kEncodedNull:
+      SetToken(CBORTokenTag::NULL_VALUE, 1);
+      return;
+    case kExpectedConversionToBase64Tag: {  // BINARY
+      int8_t bytes_read = internals::ReadTokenStart(
+          bytes_.subspan(status_.pos + 1), &token_start_type_,
+          &token_start_internal_value_);
+      int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_;
+      if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
+          status_.pos + token_byte_length > bytes_.size()) {
+        SetError(Error::CBOR_INVALID_BINARY);
+        return;
+      }
+      SetToken(CBORTokenTag::BINARY,
+               static_cast<std::ptrdiff_t>(token_byte_length));
+      return;
+    }
+    case kInitialByteForDouble: {  // DOUBLE
+      if (status_.pos + kEncodedDoubleSize > bytes_.size()) {
+        SetError(Error::CBOR_INVALID_DOUBLE);
+        return;
+      }
+      SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize);
+      return;
+    }
+    case kInitialByteForEnvelope: {  // ENVELOPE
+      if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) {
+        SetError(Error::CBOR_INVALID_ENVELOPE);
+        return;
+      }
+      // The envelope must be a byte string with 32 bit length.
+      if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) {
+        SetError(Error::CBOR_INVALID_ENVELOPE);
+        return;
+      }
+      // Read the length of the byte string.
+      token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
+          bytes_.subspan(status_.pos + 2));
+      // Make sure the payload is contained within the message.
+      if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize +
+              status_.pos >
+          static_cast<std::size_t>(bytes_.size())) {
+        SetError(Error::CBOR_INVALID_ENVELOPE);
+        return;
+      }
+      auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+      SetToken(CBORTokenTag::ENVELOPE, kEncodedEnvelopeHeaderSize + length);
+      return;
+    }
+    default: {
+      span<uint8_t> remainder =
+          bytes_.subspan(status_.pos, bytes_.size() - status_.pos);
+      assert(!remainder.empty());
+      int8_t token_start_length = internals::ReadTokenStart(
+          remainder, &token_start_type_, &token_start_internal_value_);
+      bool success = token_start_length != -1;
+      switch (token_start_type_) {
+        case MajorType::UNSIGNED:  // INT32.
+          if (!success || std::numeric_limits<int32_t>::max() <
+                              token_start_internal_value_) {
+            SetError(Error::CBOR_INVALID_INT32);
+            return;
+          }
+          SetToken(CBORTokenTag::INT32, token_start_length);
+          return;
+        case MajorType::NEGATIVE:  // INT32.
+          if (!success ||
+              std::numeric_limits<int32_t>::min() >
+                  -static_cast<int64_t>(token_start_internal_value_) - 1) {
+            SetError(Error::CBOR_INVALID_INT32);
+            return;
+          }
+          SetToken(CBORTokenTag::INT32, token_start_length);
+          return;
+        case MajorType::STRING: {  // STRING8.
+          if (!success || remainder.size() < static_cast<int64_t>(
+                                                 token_start_internal_value_)) {
+            SetError(Error::CBOR_INVALID_STRING8);
+            return;
+          }
+          auto length =
+              static_cast<std::ptrdiff_t>(token_start_internal_value_);
+          SetToken(CBORTokenTag::STRING8, token_start_length + length);
+          return;
+        }
+        case MajorType::BYTE_STRING: {  // STRING16.
+          if (!success ||
+              remainder.size() <
+                  static_cast<int64_t>(token_start_internal_value_) ||
+              // Must be divisible by 2 since UTF16 is 2 bytes per character.
+              token_start_internal_value_ & 1) {
+            SetError(Error::CBOR_INVALID_STRING16);
+            return;
+          }
+          auto length =
+              static_cast<std::ptrdiff_t>(token_start_internal_value_);
+          SetToken(CBORTokenTag::STRING16, token_start_length + length);
+          return;
+        }
+        case MajorType::ARRAY:
+        case MajorType::MAP:
+        case MajorType::TAG:
+        case MajorType::SIMPLE_VALUE:
+          SetError(Error::CBOR_UNSUPPORTED_VALUE);
+          return;
+      }
+    }
+  }
+}
+
+void CBORTokenizer::SetToken(CBORTokenTag token_tag,
+                             std::ptrdiff_t token_byte_length) {
+  token_tag_ = token_tag;
+  token_byte_length_ = token_byte_length;
+}
+
+void CBORTokenizer::SetError(Error error) {
+  token_tag_ = CBORTokenTag::ERROR_VALUE;
+  status_.error = error;
+}
+
+// =============================================================================
+// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
+// =============================================================================
+
+namespace {
+// When parsing CBOR, we limit recursion depth for objects and arrays
+// to this constant.
+static constexpr int kStackLimit = 1000;
+
+// Below are three parsing routines for CBOR, which cover enough
+// to roundtrip JSON messages.
+bool ParseMap(int32_t stack_depth,
+              CBORTokenizer* tokenizer,
+              StreamingParserHandler* out);
+bool ParseArray(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out);
+bool ParseValue(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out);
+
+void ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
+  std::vector<uint16_t> value;
+  span<uint8_t> rep = tokenizer->GetString16WireRep();
+  for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2)
+    value.push_back((rep[ii + 1] << 8) | rep[ii]);
+  out->HandleString16(span<uint16_t>(value.data(), value.size()));
+  tokenizer->Next();
+}
+
+bool ParseUTF8String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
+  assert(tokenizer->TokenTag() == CBORTokenTag::STRING8);
+  out->HandleString8(tokenizer->GetString8());
+  tokenizer->Next();
+  return true;
+}
+
+bool ParseValue(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out) {
+  if (stack_depth > kStackLimit) {
+    out->HandleError(
+        Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos});
+    return false;
+  }
+  // Skip past the envelope to get to what's inside.
+  if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE)
+    tokenizer->EnterEnvelope();
+  switch (tokenizer->TokenTag()) {
+    case CBORTokenTag::ERROR_VALUE:
+      out->HandleError(tokenizer->Status());
+      return false;
+    case CBORTokenTag::DONE:
+      out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
+                              tokenizer->Status().pos});
+      return false;
+    case CBORTokenTag::TRUE_VALUE:
+      out->HandleBool(true);
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::FALSE_VALUE:
+      out->HandleBool(false);
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::NULL_VALUE:
+      out->HandleNull();
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::INT32:
+      out->HandleInt32(tokenizer->GetInt32());
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::DOUBLE:
+      out->HandleDouble(tokenizer->GetDouble());
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::STRING8:
+      return ParseUTF8String(tokenizer, out);
+    case CBORTokenTag::STRING16:
+      ParseUTF16String(tokenizer, out);
+      return true;
+    case CBORTokenTag::BINARY: {
+      out->HandleBinary(tokenizer->GetBinary());
+      tokenizer->Next();
+      return true;
+    }
+    case CBORTokenTag::MAP_START:
+      return ParseMap(stack_depth + 1, tokenizer, out);
+    case CBORTokenTag::ARRAY_START:
+      return ParseArray(stack_depth + 1, tokenizer, out);
+    default:
+      out->HandleError(
+          Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos});
+      return false;
+  }
+}
+
+// |bytes| must start with the indefinite length array byte, so basically,
+// ParseArray may only be called after an indefinite length array has been
+// detected.
+bool ParseArray(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out) {
+  assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
+  tokenizer->Next();
+  out->HandleArrayBegin();
+  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
+    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
+      out->HandleError(
+          Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos});
+      return false;
+    }
+    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
+      out->HandleError(tokenizer->Status());
+      return false;
+    }
+    // Parse value.
+    if (!ParseValue(stack_depth, tokenizer, out))
+      return false;
+  }
+  out->HandleArrayEnd();
+  tokenizer->Next();
+  return true;
+}
+
+// |bytes| must start with the indefinite length array byte, so basically,
+// ParseArray may only be called after an indefinite length array has been
+// detected.
+bool ParseMap(int32_t stack_depth,
+              CBORTokenizer* tokenizer,
+              StreamingParserHandler* out) {
+  assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START);
+  out->HandleMapBegin();
+  tokenizer->Next();
+  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
+    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
+      out->HandleError(
+          Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos});
+      return false;
+    }
+    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
+      out->HandleError(tokenizer->Status());
+      return false;
+    }
+    // Parse key.
+    if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
+      if (!ParseUTF8String(tokenizer, out))
+        return false;
+    } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
+      ParseUTF16String(tokenizer, out);
+    } else {
+      out->HandleError(
+          Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos});
+      return false;
+    }
+    // Parse value.
+    if (!ParseValue(stack_depth, tokenizer, out))
+      return false;
+  }
+  out->HandleMapEnd();
+  tokenizer->Next();
+  return true;
+}
+}  // namespace
+
+void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out) {
+  if (bytes.empty()) {
+    out->HandleError(Status{Error::CBOR_NO_INPUT, 0});
+    return;
+  }
+  if (bytes[0] != kInitialByteForEnvelope) {
+    out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0});
+    return;
+  }
+  CBORTokenizer tokenizer(bytes);
+  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
+    out->HandleError(tokenizer.Status());
+    return;
+  }
+  // We checked for the envelope start byte above, so the tokenizer
+  // must agree here, since it's not an error.
+  assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE);
+  tokenizer.EnterEnvelope();
+  if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) {
+    out->HandleError(
+        Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos});
+    return;
+  }
+  if (!ParseMap(/*stack_depth=*/1, &tokenizer, out))
+    return;
+  if (tokenizer.TokenTag() == CBORTokenTag::DONE)
+    return;
+  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
+    out->HandleError(tokenizer.Status());
+    return;
+  }
+  out->HandleError(Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos});
+}
+}  // namespace cbor
+
+namespace json {
+
+// =============================================================================
+// json::NewJSONEncoder - for encoding streaming parser events as JSON
+// =============================================================================
+
+namespace {
+// Prints |value| to |out| with 4 hex digits, most significant chunk first.
+void PrintHex(uint16_t value, std::string* out) {
+  for (int ii = 3; ii >= 0; --ii) {
+    int four_bits = 0xf & (value >> (4 * ii));
+    out->append(1, four_bits + ((four_bits <= 9) ? '0' : ('a' - 10)));
+  }
+}
+
+// In the writer below, we maintain a stack of State instances.
+// It is just enough to emit the appropriate delimiters and brackets
+// in JSON.
+enum class Container {
+  // Used for the top-level, initial state.
+  NONE,
+  // Inside a JSON object.
+  MAP,
+  // Inside a JSON array.
+  ARRAY
+};
+class State {
+ public:
+  explicit State(Container container) : container_(container) {}
+  void StartElement(std::string* out) {
+    assert(container_ != Container::NONE || size_ == 0);
+    if (size_ != 0) {
+      char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':';
+      out->append(1, delim);
+    }
+    ++size_;
+  }
+  Container container() const { return container_; }
+
+ private:
+  Container container_ = Container::NONE;
+  int size_ = 0;
+};
+
+constexpr char kBase64Table[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz0123456789+/";
+
+void Base64Encode(const span<uint8_t>& in, std::string* out) {
+  // The following three cases are based on the tables in the example
+  // section in https://en.wikipedia.org/wiki/Base64. We process three
+  // input bytes at a time, emitting 4 output bytes at a time.
+  std::ptrdiff_t ii = 0;
+
+  // While possible, process three input bytes.
+  for (; ii + 3 <= in.size(); ii += 3) {
+    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2];
+    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
+    out->push_back(kBase64Table[twentyfour_bits & 0x3f]);
+  }
+  if (ii + 2 <= in.size()) {  // Process two input bytes.
+    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8);
+    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
+    out->push_back('=');  // Emit padding.
+    return;
+  }
+  if (ii + 1 <= in.size()) {  // Process a single input byte.
+    uint32_t twentyfour_bits = (in[ii] << 16);
+    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
+    out->push_back('=');  // Emit padding.
+    out->push_back('=');  // Emit padding.
+  }
+}
+
+// Implements a handler for JSON parser events to emit a JSON string.
+class JSONEncoder : public StreamingParserHandler {
+ public:
+  JSONEncoder(const Platform* platform, std::string* out, Status* status)
+      : platform_(platform), out_(out), status_(status) {
+    *status_ = Status();
+    state_.emplace(Container::NONE);
+  }
+
+  void HandleMapBegin() override {
+    if (!status_->ok())
+      return;
+    assert(!state_.empty());
+    state_.top().StartElement(out_);
+    state_.emplace(Container::MAP);
+    out_->append("{");
+  }
+
+  void HandleMapEnd() override {
+    if (!status_->ok())
+      return;
+    assert(state_.size() >= 2 && state_.top().container() == Container::MAP);
+    state_.pop();
+    out_->append("}");
+  }
+
+  void HandleArrayBegin() override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    state_.emplace(Container::ARRAY);
+    out_->append("[");
+  }
+
+  void HandleArrayEnd() override {
+    if (!status_->ok())
+      return;
+    assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY);
+    state_.pop();
+    out_->append("]");
+  }
+
+  void HandleString16(span<uint16_t> chars) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("\"");
+    for (const uint16_t ch : chars) {
+      if (ch == '"') {
+        out_->append("\\\"");
+      } else if (ch == '\\') {
+        out_->append("\\\\");
+      } else if (ch == '\b') {
+        out_->append("\\b");
+      } else if (ch == '\f') {
+        out_->append("\\f");
+      } else if (ch == '\n') {
+        out_->append("\\n");
+      } else if (ch == '\r') {
+        out_->append("\\r");
+      } else if (ch == '\t') {
+        out_->append("\\t");
+      } else if (ch >= 32 && ch <= 126) {
+        out_->append(1, ch);
+      } else {
+        out_->append("\\u");
+        PrintHex(ch, out_);
+      }
+    }
+    out_->append("\"");
+  }
+
+  void HandleString8(span<uint8_t> chars) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("\"");
+    for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) {
+      uint8_t c = chars[ii];
+      if (c == '"') {
+        out_->append("\\\"");
+      } else if (c == '\\') {
+        out_->append("\\\\");
+      } else if (c == '\b') {
+        out_->append("\\b");
+      } else if (c == '\f') {
+        out_->append("\\f");
+      } else if (c == '\n') {
+        out_->append("\\n");
+      } else if (c == '\r') {
+        out_->append("\\r");
+      } else if (c == '\t') {
+        out_->append("\\t");
+      } else if (c >= 32 && c <= 126) {
+        out_->append(1, c);
+      } else if (c < 32) {
+        out_->append("\\u");
+        PrintHex(static_cast<uint16_t>(c), out_);
+      } else {
+        // Inspect the leading byte to figure out how long the utf8
+        // byte sequence is; while doing this initialize |codepoint|
+        // with the first few bits.
+        // See table in: https://en.wikipedia.org/wiki/UTF-8
+        // byte one is 110x xxxx -> 2 byte utf8 sequence
+        // byte one is 1110 xxxx -> 3 byte utf8 sequence
+        // byte one is 1111 0xxx -> 4 byte utf8 sequence
+        uint32_t codepoint;
+        int num_bytes_left;
+        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
+          num_bytes_left = 1;
+          codepoint = c & 0x1f;
+        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
+          num_bytes_left = 2;
+          codepoint = c & 0x0f;
+        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
+          codepoint = c & 0x07;
+          num_bytes_left = 3;
+        } else {
+          continue;  // invalid leading byte
+        }
+
+        // If we have enough bytes in our input, decode the remaining ones
+        // belonging to this Unicode character into |codepoint|.
+        if (ii + num_bytes_left > chars.size())
+          continue;
+        while (num_bytes_left > 0) {
+          c = chars[++ii];
+          --num_bytes_left;
+          // Check the next byte is a continuation byte, that is 10xx xxxx.
+          if ((c & 0xc0) != 0x80)
+            continue;
+          codepoint = (codepoint << 6) | (c & 0x3f);
+        }
+
+        // Disallow overlong encodings for ascii characters, as these
+        // would include " and other characters significant to JSON
+        // string termination / control.
+        if (codepoint < 0x7f)
+          continue;
+        // Invalid in UTF8, and can't be represented in UTF16 anyway.
+        if (codepoint > 0x10ffff)
+          continue;
+
+        // So, now we transcode to UTF16,
+        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
+        // for either one or two 16 bit characters.
+        if (codepoint < 0xffff) {
+          out_->append("\\u");
+          PrintHex(static_cast<uint16_t>(codepoint), out_);
+          continue;
+        }
+        codepoint -= 0x10000;
+        // high surrogate
+        out_->append("\\u");
+        PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_);
+        // low surrogate
+        out_->append("\\u");
+        PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_);
+      }
+    }
+    out_->append("\"");
+  }
+
+  void HandleBinary(span<uint8_t> bytes) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("\"");
+    Base64Encode(bytes, out_);
+    out_->append("\"");
+  }
+
+  void HandleDouble(double value) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    std::unique_ptr<char[]> str_value = platform_->DToStr(value);
+
+    // DToStr may fail to emit a 0 before the decimal dot. E.g. this is
+    // the case in base::NumberToString in Chromium (which is based on
+    // dmg_fp). So, much like
+    // https://cs.chromium.org/chromium/src/base/json/json_writer.cc
+    // we probe for this and emit the leading 0 anyway if necessary.
+    const char* chars = str_value.get();
+    if (chars[0] == '.') {
+      out_->append("0");
+    } else if (chars[0] == '-' && chars[1] == '.') {
+      out_->append("-0");
+      ++chars;
+    }
+    out_->append(chars);
+  }
+
+  void HandleInt32(int32_t value) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append(std::to_string(value));
+  }
+
+  void HandleBool(bool value) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append(value ? "true" : "false");
+  }
+
+  void HandleNull() override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("null");
+  }
+
+  void HandleError(Status error) override {
+    assert(!error.ok());
+    *status_ = error;
+    out_->clear();
+  }
+
+ private:
+  const Platform* platform_;
+  std::string* out_;
+  Status* status_;
+  std::stack<State> state_;
+};
+}  // namespace
+
+std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform,
+                                                       std::string* out,
+                                                       Status* status) {
+  return std::unique_ptr<StreamingParserHandler>(
+      new JSONEncoder(platform, out, status));
+}
+
+// =============================================================================
+// json::ParseJSON - for receiving streaming parser events for JSON.
+// =============================================================================
+
+namespace {
+const int kStackLimit = 1000;
+
+enum Token {
+  ObjectBegin,
+  ObjectEnd,
+  ArrayBegin,
+  ArrayEnd,
+  StringLiteral,
+  Number,
+  BoolTrue,
+  BoolFalse,
+  NullToken,
+  ListSeparator,
+  ObjectPairSeparator,
+  InvalidToken,
+  NoInput
+};
+
+const char* const kNullString = "null";
+const char* const kTrueString = "true";
+const char* const kFalseString = "false";
+
+template <typename Char>
+class JsonParser {
+ public:
+  JsonParser(const Platform* platform, StreamingParserHandler* handler)
+      : platform_(platform), handler_(handler) {}
+
+  void Parse(const Char* start, std::size_t length) {
+    start_pos_ = start;
+    const Char* end = start + length;
+    const Char* tokenEnd;
+    ParseValue(start, end, &tokenEnd, 0);
+    if (tokenEnd != end) {
+      HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd);
+    }
+  }
+
+ private:
+  bool CharsToDouble(const uint16_t* chars,
+                     std::size_t length,
+                     double* result) {
+    std::string buffer;
+    buffer.reserve(length + 1);
+    for (std::size_t ii = 0; ii < length; ++ii) {
+      bool is_ascii = !(chars[ii] & ~0x7F);
+      if (!is_ascii)
+        return false;
+      buffer.push_back(static_cast<char>(chars[ii]));
+    }
+    return platform_->StrToD(buffer.c_str(), result);
+  }
+
+  bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) {
+    std::string buffer(reinterpret_cast<const char*>(chars), length);
+    return platform_->StrToD(buffer.c_str(), result);
+  }
+
+  static bool ParseConstToken(const Char* start,
+                              const Char* end,
+                              const Char** token_end,
+                              const char* token) {
+    // |token| is \0 terminated, it's one of the constants at top of the file.
+    while (start < end && *token != '\0' && *start++ == *token++) {
+    }
+    if (*token != '\0')
+      return false;
+    *token_end = start;
+    return true;
+  }
+
+  static bool ReadInt(const Char* start,
+                      const Char* end,
+                      const Char** token_end,
+                      bool allow_leading_zeros) {
+    if (start == end)
+      return false;
+    bool has_leading_zero = '0' == *start;
+    int length = 0;
+    while (start < end && '0' <= *start && *start <= '9') {
+      ++start;
+      ++length;
+    }
+    if (!length)
+      return false;
+    if (!allow_leading_zeros && length > 1 && has_leading_zero)
+      return false;
+    *token_end = start;
+    return true;
+  }
+
+  static bool ParseNumberToken(const Char* start,
+                               const Char* end,
+                               const Char** token_end) {
+    // We just grab the number here. We validate the size in DecodeNumber.
+    // According to RFC4627, a valid number is: [minus] int [frac] [exp]
+    if (start == end)
+      return false;
+    Char c = *start;
+    if ('-' == c)
+      ++start;
+
+    if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false))
+      return false;
+    if (start == end) {
+      *token_end = start;
+      return true;
+    }
+
+    // Optional fraction part
+    c = *start;
+    if ('.' == c) {
+      ++start;
+      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
+        return false;
+      if (start == end) {
+        *token_end = start;
+        return true;
+      }
+      c = *start;
+    }
+
+    // Optional exponent part
+    if ('e' == c || 'E' == c) {
+      ++start;
+      if (start == end)
+        return false;
+      c = *start;
+      if ('-' == c || '+' == c) {
+        ++start;
+        if (start == end)
+          return false;
+      }
+      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
+        return false;
+    }
+
+    *token_end = start;
+    return true;
+  }
+
+  static bool ReadHexDigits(const Char* start,
+                            const Char* end,
+                            const Char** token_end,
+                            int digits) {
+    if (end - start < digits)
+      return false;
+    for (int i = 0; i < digits; ++i) {
+      Char c = *start++;
+      if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
+            ('A' <= c && c <= 'F')))
+        return false;
+    }
+    *token_end = start;
+    return true;
+  }
+
+  static bool ParseStringToken(const Char* start,
+                               const Char* end,
+                               const Char** token_end) {
+    while (start < end) {
+      Char c = *start++;
+      if ('\\' == c) {
+        if (start == end)
+          return false;
+        c = *start++;
+        // Make sure the escaped char is valid.
+        switch (c) {
+          case 'x':
+            if (!ReadHexDigits(start, end, &start, 2))
+              return false;
+            break;
+          case 'u':
+            if (!ReadHexDigits(start, end, &start, 4))
+              return false;
+            break;
+          case '\\':
+          case '/':
+          case 'b':
+          case 'f':
+          case 'n':
+          case 'r':
+          case 't':
+          case 'v':
+          case '"':
+            break;
+          default:
+            return false;
+        }
+      } else if ('"' == c) {
+        *token_end = start;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static bool SkipComment(const Char* start,
+                          const Char* end,
+                          const Char** comment_end) {
+    if (start == end)
+      return false;
+
+    if (*start != '/' || start + 1 >= end)
+      return false;
+    ++start;
+
+    if (*start == '/') {
+      // Single line comment, read to newline.
+      for (++start; start < end; ++start) {
+        if (*start == '\n' || *start == '\r') {
+          *comment_end = start + 1;
+          return true;
+        }
+      }
+      *comment_end = end;
+      // Comment reaches end-of-input, which is fine.
+      return true;
+    }
+
+    if (*start == '*') {
+      Char previous = '\0';
+      // Block comment, read until end marker.
+      for (++start; start < end; previous = *start++) {
+        if (previous == '*' && *start == '/') {
+          *comment_end = start + 1;
+          return true;
+        }
+      }
+      // Block comment must close before end-of-input.
+      return false;
+    }
+
+    return false;
+  }
+
+  static bool IsSpaceOrNewLine(Char c) {
+    // \v = vertial tab; \f = form feed page break.
+    return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' ||
+           c == '\t';
+  }
+
+  static void SkipWhitespaceAndComments(const Char* start,
+                                        const Char* end,
+                                        const Char** whitespace_end) {
+    while (start < end) {
+      if (IsSpaceOrNewLine(*start)) {
+        ++start;
+      } else if (*start == '/') {
+        const Char* comment_end;
+        if (!SkipComment(start, end, &comment_end))
+          break;
+        start = comment_end;
+      } else {
+        break;
+      }
+    }
+    *whitespace_end = start;
+  }
+
+  static Token ParseToken(const Char* start,
+                          const Char* end,
+                          const Char** tokenStart,
+                          const Char** token_end) {
+    SkipWhitespaceAndComments(start, end, tokenStart);
+    start = *tokenStart;
+
+    if (start == end)
+      return NoInput;
+
+    switch (*start) {
+      case 'n':
+        if (ParseConstToken(start, end, token_end, kNullString))
+          return NullToken;
+        break;
+      case 't':
+        if (ParseConstToken(start, end, token_end, kTrueString))
+          return BoolTrue;
+        break;
+      case 'f':
+        if (ParseConstToken(start, end, token_end, kFalseString))
+          return BoolFalse;
+        break;
+      case '[':
+        *token_end = start + 1;
+        return ArrayBegin;
+      case ']':
+        *token_end = start + 1;
+        return ArrayEnd;
+      case ',':
+        *token_end = start + 1;
+        return ListSeparator;
+      case '{':
+        *token_end = start + 1;
+        return ObjectBegin;
+      case '}':
+        *token_end = start + 1;
+        return ObjectEnd;
+      case ':':
+        *token_end = start + 1;
+        return ObjectPairSeparator;
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+      case '-':
+        if (ParseNumberToken(start, end, token_end))
+          return Number;
+        break;
+      case '"':
+        if (ParseStringToken(start + 1, end, token_end))
+          return StringLiteral;
+        break;
+    }
+    return InvalidToken;
+  }
+
+  static int HexToInt(Char c) {
+    if ('0' <= c && c <= '9')
+      return c - '0';
+    if ('A' <= c && c <= 'F')
+      return c - 'A' + 10;
+    if ('a' <= c && c <= 'f')
+      return c - 'a' + 10;
+    assert(false);  // Unreachable.
+    return 0;
+  }
+
+  static bool DecodeString(const Char* start,
+                           const Char* end,
+                           std::vector<uint16_t>* output) {
+    if (start == end)
+      return true;
+    if (start > end)
+      return false;
+    output->reserve(end - start);
+    while (start < end) {
+      uint16_t c = *start++;
+      // If the |Char| we're dealing with is really a byte, then
+      // we have utf8 here, and we need to check for multibyte characters
+      // and transcode them to utf16 (either one or two utf16 chars).
+      if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) {
+        // Inspect the leading byte to figure out how long the utf8
+        // byte sequence is; while doing this initialize |codepoint|
+        // with the first few bits.
+        // See table in: https://en.wikipedia.org/wiki/UTF-8
+        // byte one is 110x xxxx -> 2 byte utf8 sequence
+        // byte one is 1110 xxxx -> 3 byte utf8 sequence
+        // byte one is 1111 0xxx -> 4 byte utf8 sequence
+        uint32_t codepoint;
+        int num_bytes_left;
+        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
+          num_bytes_left = 1;
+          codepoint = c & 0x1f;
+        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
+          num_bytes_left = 2;
+          codepoint = c & 0x0f;
+        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
+          codepoint = c & 0x07;
+          num_bytes_left = 3;
+        } else {
+          return false;  // invalid leading byte
+        }
+
+        // If we have enough bytes in our inpput, decode the remaining ones
+        // belonging to this Unicode character into |codepoint|.
+        if (start + num_bytes_left > end)
+          return false;
+        while (num_bytes_left > 0) {
+          c = *start++;
+          --num_bytes_left;
+          // Check the next byte is a continuation byte, that is 10xx xxxx.
+          if ((c & 0xc0) != 0x80)
+            return false;
+          codepoint = (codepoint << 6) | (c & 0x3f);
+        }
+
+        // Disallow overlong encodings for ascii characters, as these
+        // would include " and other characters significant to JSON
+        // string termination / control.
+        if (codepoint < 0x7f)
+          return false;
+        // Invalid in UTF8, and can't be represented in UTF16 anyway.
+        if (codepoint > 0x10ffff)
+          return false;
+
+        // So, now we transcode to UTF16,
+        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
+        // for either one or two 16 bit characters.
+        if (codepoint < 0xffff) {
+          output->push_back(codepoint);
+          continue;
+        }
+        codepoint -= 0x10000;
+        output->push_back((codepoint >> 10) + 0xd800);    // high surrogate
+        output->push_back((codepoint & 0x3ff) + 0xdc00);  // low surrogate
+        continue;
+      }
+      if ('\\' != c) {
+        output->push_back(c);
+        continue;
+      }
+      if (start == end)
+        return false;
+      c = *start++;
+
+      if (c == 'x') {
+        // \x is not supported.
+        return false;
+      }
+
+      switch (c) {
+        case '"':
+        case '/':
+        case '\\':
+          break;
+        case 'b':
+          c = '\b';
+          break;
+        case 'f':
+          c = '\f';
+          break;
+        case 'n':
+          c = '\n';
+          break;
+        case 'r':
+          c = '\r';
+          break;
+        case 't':
+          c = '\t';
+          break;
+        case 'v':
+          c = '\v';
+          break;
+        case 'u':
+          c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) +
+              (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3));
+          start += 4;
+          break;
+        default:
+          return false;
+      }
+      output->push_back(c);
+    }
+    return true;
+  }
+
+  void ParseValue(const Char* start,
+                  const Char* end,
+                  const Char** value_token_end,
+                  int depth) {
+    if (depth > kStackLimit) {
+      HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start);
+      return;
+    }
+    const Char* token_start;
+    const Char* token_end;
+    Token token = ParseToken(start, end, &token_start, &token_end);
+    switch (token) {
+      case NoInput:
+        HandleError(Error::JSON_PARSER_NO_INPUT, token_start);
+        return;
+      case InvalidToken:
+        HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start);
+        return;
+      case NullToken:
+        handler_->HandleNull();
+        break;
+      case BoolTrue:
+        handler_->HandleBool(true);
+        break;
+      case BoolFalse:
+        handler_->HandleBool(false);
+        break;
+      case Number: {
+        double value;
+        if (!CharsToDouble(token_start, token_end - token_start, &value)) {
+          HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start);
+          return;
+        }
+        if (value >= std::numeric_limits<int32_t>::min() &&
+            value <= std::numeric_limits<int32_t>::max() &&
+            static_cast<int32_t>(value) == value)
+          handler_->HandleInt32(static_cast<int32_t>(value));
+        else
+          handler_->HandleDouble(value);
+        break;
+      }
+      case StringLiteral: {
+        std::vector<uint16_t> value;
+        bool ok = DecodeString(token_start + 1, token_end - 1, &value);
+        if (!ok) {
+          HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
+          return;
+        }
+        handler_->HandleString16(span<uint16_t>(value.data(), value.size()));
+        break;
+      }
+      case ArrayBegin: {
+        handler_->HandleArrayBegin();
+        start = token_end;
+        token = ParseToken(start, end, &token_start, &token_end);
+        while (token != ArrayEnd) {
+          ParseValue(start, end, &token_end, depth + 1);
+          if (error_)
+            return;
+
+          // After a list value, we expect a comma or the end of the list.
+          start = token_end;
+          token = ParseToken(start, end, &token_start, &token_end);
+          if (token == ListSeparator) {
+            start = token_end;
+            token = ParseToken(start, end, &token_start, &token_end);
+            if (token == ArrayEnd) {
+              HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start);
+              return;
+            }
+          } else if (token != ArrayEnd) {
+            // Unexpected value after list value. Bail out.
+            HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
+                        token_start);
+            return;
+          }
+        }
+        handler_->HandleArrayEnd();
+        break;
+      }
+      case ObjectBegin: {
+        handler_->HandleMapBegin();
+        start = token_end;
+        token = ParseToken(start, end, &token_start, &token_end);
+        while (token != ObjectEnd) {
+          if (token != StringLiteral) {
+            HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED,
+                        token_start);
+            return;
+          }
+          std::vector<uint16_t> key;
+          if (!DecodeString(token_start + 1, token_end - 1, &key)) {
+            HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
+            return;
+          }
+          handler_->HandleString16(span<uint16_t>(key.data(), key.size()));
+          start = token_end;
+
+          token = ParseToken(start, end, &token_start, &token_end);
+          if (token != ObjectPairSeparator) {
+            HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start);
+            return;
+          }
+          start = token_end;
+
+          ParseValue(start, end, &token_end, depth + 1);
+          if (error_)
+            return;
+          start = token_end;
+
+          // After a key/value pair, we expect a comma or the end of the
+          // object.
+          token = ParseToken(start, end, &token_start, &token_end);
+          if (token == ListSeparator) {
+            start = token_end;
+            token = ParseToken(start, end, &token_start, &token_end);
+            if (token == ObjectEnd) {
+              HandleError(Error::JSON_PARSER_UNEXPECTED_MAP_END, token_start);
+              return;
+            }
+          } else if (token != ObjectEnd) {
+            // Unexpected value after last object value. Bail out.
+            HandleError(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED,
+                        token_start);
+            return;
+          }
+        }
+        handler_->HandleMapEnd();
+        break;
+      }
+
+      default:
+        // We got a token that's not a value.
+        HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start);
+        return;
+    }
+
+    SkipWhitespaceAndComments(token_end, end, value_token_end);
+  }
+
+  void HandleError(Error error, const Char* pos) {
+    assert(error != Error::OK);
+    if (!error_) {
+      handler_->HandleError(Status{error, pos - start_pos_});
+      error_ = true;
+    }
+  }
+
+  const Char* start_pos_ = nullptr;
+  bool error_ = false;
+  const Platform* platform_;
+  StreamingParserHandler* handler_;
+};
+}  // namespace
+
+void ParseJSON(const Platform* platform,
+               span<uint8_t> chars,
+               StreamingParserHandler* handler) {
+  JsonParser<uint8_t> parser(platform, handler);
+  parser.Parse(chars.data(), chars.size());
+}
+
+void ParseJSON(const Platform* platform,
+               span<uint16_t> chars,
+               StreamingParserHandler* handler) {
+  JsonParser<uint16_t> parser(platform, handler);
+  parser.Parse(chars.data(), chars.size());
+}
+}  // namespace json
+}  // namespace inspector_protocol_encoding
diff --git a/third_party/inspector_protocol/lib/CBOR_h.template b/third_party/inspector_protocol/encoding/encoding.h
similarity index 65%
rename from third_party/inspector_protocol/lib/CBOR_h.template
rename to third_party/inspector_protocol/encoding/encoding.h
index 9d28adb..b958ff4 100644
--- a/third_party/inspector_protocol/lib/CBOR_h.template
+++ b/third_party/inspector_protocol/encoding/encoding.h
@@ -1,75 +1,21 @@
-{# This template is generated by gen_cbor_templates.py. #}
-// Generated by lib/CBOR_h.template.
-
 // Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef {{"_".join(config.protocol.namespace)}}_CBOR_h
-#define {{"_".join(config.protocol.namespace)}}_CBOR_h
+#ifndef INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_
+#define INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_
 
 #include <cstddef>
 #include <cstdint>
 #include <memory>
+#include <string>
 #include <vector>
 
-{% for namespace in config.protocol.namespace %}
-namespace {{namespace}} {
-{% endfor %}
+namespace inspector_protocol_encoding {
 
-// ===== encoding/status.h =====
-
-// Error codes.
-enum class Error {
-  OK = 0,
-  // JSON parsing errors - json_parser.{h,cc}.
-  JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
-  JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
-  JSON_PARSER_NO_INPUT = 0x03,
-  JSON_PARSER_INVALID_TOKEN = 0x04,
-  JSON_PARSER_INVALID_NUMBER = 0x05,
-  JSON_PARSER_INVALID_STRING = 0x06,
-  JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07,
-  JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08,
-  JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09,
-  JSON_PARSER_COLON_EXPECTED = 0x0a,
-  JSON_PARSER_UNEXPECTED_OBJECT_END = 0x0b,
-  JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED = 0x0c,
-  JSON_PARSER_VALUE_EXPECTED = 0x0d,
-
-  CBOR_INVALID_INT32 = 0x0e,
-  CBOR_INVALID_DOUBLE = 0x0f,
-  CBOR_INVALID_ENVELOPE = 0x10,
-  CBOR_INVALID_STRING8 = 0x11,
-  CBOR_INVALID_STRING16 = 0x12,
-  CBOR_INVALID_BINARY = 0x13,
-  CBOR_UNSUPPORTED_VALUE = 0x14,
-  CBOR_NO_INPUT = 0x15,
-  CBOR_INVALID_START_BYTE = 0x16,
-  CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17,
-  CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18,
-  CBOR_UNEXPECTED_EOF_IN_MAP = 0x19,
-  CBOR_INVALID_MAP_KEY = 0x1a,
-  CBOR_STACK_LIMIT_EXCEEDED = 0x1b,
-  CBOR_STRING8_MUST_BE_7BIT = 0x1c,
-  CBOR_TRAILING_JUNK = 0x1d,
-  CBOR_MAP_START_EXPECTED = 0x1e,
-};
-
-// A status value with position that can be copied. The default status
-// is OK. Usually, error status values should come with a valid position.
-struct Status {
-  static constexpr std::ptrdiff_t npos() { return -1; }
-
-  bool ok() const { return error == Error::OK; }
-
-  Error error = Error::OK;
-  std::ptrdiff_t pos = npos();
-  Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
-  Status() = default;
-};
-
-// ===== encoding/span.h =====
+// =============================================================================
+// span - sequence of bytes
+// =============================================================================
 
 // This template is similar to std::span, which will be included in C++20.  Like
 // std::span it uses ptrdiff_t, which is signed (and thus a bit annoying
@@ -107,19 +53,78 @@
   index_type size_;
 };
 
-// ===== encoding/json_parser_handler.h =====
+template <typename T>
+span<T> SpanFromVector(const std::vector<T>& v) {
+  return span<T>(v.data(), v.size());
+}
 
-// Handler interface for JSON parser events. See also json_parser.h.
-class JSONParserHandler {
+inline span<uint8_t> SpanFromStdString(const std::string& v) {
+  return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size());
+}
+
+// Error codes.
+enum class Error {
+  OK = 0,
+  // JSON parsing errors - json_parser.{h,cc}.
+  JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
+  JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
+  JSON_PARSER_NO_INPUT = 0x03,
+  JSON_PARSER_INVALID_TOKEN = 0x04,
+  JSON_PARSER_INVALID_NUMBER = 0x05,
+  JSON_PARSER_INVALID_STRING = 0x06,
+  JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07,
+  JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08,
+  JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09,
+  JSON_PARSER_COLON_EXPECTED = 0x0a,
+  JSON_PARSER_UNEXPECTED_MAP_END = 0x0b,
+  JSON_PARSER_COMMA_OR_MAP_END_EXPECTED = 0x0c,
+  JSON_PARSER_VALUE_EXPECTED = 0x0d,
+
+  CBOR_INVALID_INT32 = 0x0e,
+  CBOR_INVALID_DOUBLE = 0x0f,
+  CBOR_INVALID_ENVELOPE = 0x10,
+  CBOR_INVALID_STRING8 = 0x11,
+  CBOR_INVALID_STRING16 = 0x12,
+  CBOR_INVALID_BINARY = 0x13,
+  CBOR_UNSUPPORTED_VALUE = 0x14,
+  CBOR_NO_INPUT = 0x15,
+  CBOR_INVALID_START_BYTE = 0x16,
+  CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17,
+  CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18,
+  CBOR_UNEXPECTED_EOF_IN_MAP = 0x19,
+  CBOR_INVALID_MAP_KEY = 0x1a,
+  CBOR_STACK_LIMIT_EXCEEDED = 0x1b,
+  CBOR_STRING8_MUST_BE_7BIT = 0x1c,
+  CBOR_TRAILING_JUNK = 0x1d,
+  CBOR_MAP_START_EXPECTED = 0x1e,
+};
+
+// A status value with position that can be copied. The default status
+// is OK. Usually, error status values should come with a valid position.
+struct Status {
+  static constexpr std::ptrdiff_t npos() { return -1; }
+
+  bool ok() const { return error == Error::OK; }
+
+  Error error = Error::OK;
+  std::ptrdiff_t pos = npos();
+  Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
+  Status() = default;
+};
+
+// Handler interface for parser events emitted by a streaming parser.
+// See cbor::NewCBOREncoder, cbor::ParseCBOR, json::NewJSONEncoder,
+// json::ParseJSON.
+class StreamingParserHandler {
  public:
-  virtual ~JSONParserHandler() = default;
-  virtual void HandleObjectBegin() = 0;
-  virtual void HandleObjectEnd() = 0;
+  virtual ~StreamingParserHandler() = default;
+  virtual void HandleMapBegin() = 0;
+  virtual void HandleMapEnd() = 0;
   virtual void HandleArrayBegin() = 0;
   virtual void HandleArrayEnd() = 0;
   virtual void HandleString8(span<uint8_t> chars) = 0;
   virtual void HandleString16(span<uint16_t> chars) = 0;
-  virtual void HandleBinary(std::vector<uint8_t> bytes) = 0;
+  virtual void HandleBinary(span<uint8_t> bytes) = 0;
   virtual void HandleDouble(double value) = 0;
   virtual void HandleInt32(int32_t value) = 0;
   virtual void HandleBool(bool value) = 0;
@@ -132,97 +137,7 @@
   virtual void HandleError(Status error) = 0;
 };
 
-// ===== encoding/cbor_internals.h =====
-
 namespace cbor {
-enum class MajorType;
-}
-
-namespace cbor_internals {
-
-// Reads the start of a token with definitive size from |bytes|.
-// |type| is the major type as specified in RFC 7049 Section 2.1.
-// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
-// (e.g. for BYTE_STRING).
-// If successful, returns the number of bytes read. Otherwise returns -1.
-int8_t ReadTokenStart(span<uint8_t> bytes, cbor::MajorType* type,
-                      uint64_t* value);
-
-// Writes the start of a token with |type|. The |value| may indicate the size,
-// or it may be the payload if the value is an unsigned integer.
-void WriteTokenStart(cbor::MajorType type, uint64_t value,
-                     std::vector<uint8_t>* encoded);
-}  // namespace cbor_internals
-
-// ===== encoding/cbor.h =====
-
-
-namespace cbor {
-
-// The major types from RFC 7049 Section 2.1.
-enum class MajorType {
-  UNSIGNED = 0,
-  NEGATIVE = 1,
-  BYTE_STRING = 2,
-  STRING = 3,
-  ARRAY = 4,
-  MAP = 5,
-  TAG = 6,
-  SIMPLE_VALUE = 7
-};
-
-// Indicates the number of bits the "initial byte" needs to be shifted to the
-// right after applying |kMajorTypeMask| to produce the major type in the
-// lowermost bits.
-static constexpr uint8_t kMajorTypeBitShift = 5u;
-// Mask selecting the low-order 5 bits of the "initial byte", which is where
-// the additional information is encoded.
-static constexpr uint8_t kAdditionalInformationMask = 0x1f;
-// Mask selecting the high-order 3 bits of the "initial byte", which indicates
-// the major type of the encoded value.
-static constexpr uint8_t kMajorTypeMask = 0xe0;
-// Indicates the integer is in the following byte.
-static constexpr uint8_t kAdditionalInformation1Byte = 24u;
-// Indicates the integer is in the next 2 bytes.
-static constexpr uint8_t kAdditionalInformation2Bytes = 25u;
-// Indicates the integer is in the next 4 bytes.
-static constexpr uint8_t kAdditionalInformation4Bytes = 26u;
-// Indicates the integer is in the next 8 bytes.
-static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
-
-// Encodes the initial byte, consisting of the |type| in the first 3 bits
-// followed by 5 bits of |additional_info|.
-constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
-  return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
-         (additional_info & kAdditionalInformationMask);
-}
-
-// TAG 24 indicates that what follows is a byte string which is
-// encoded in CBOR format. We use this as a wrapper for
-// maps and arrays, allowing us to skip them, because the
-// byte string carries its size (byte length).
-// https://tools.ietf.org/html/rfc7049#section-2.4.4.1
-static constexpr uint8_t kInitialByteForEnvelope =
-    EncodeInitialByte(MajorType::TAG, 24);
-// The initial byte for a byte string with at most 2^32 bytes
-// of payload. This is used for envelope encoding, even if
-// the byte string is shorter.
-static constexpr uint8_t kInitialByteFor32BitLengthByteString =
-    EncodeInitialByte(MajorType::BYTE_STRING, 26);
-
-// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
-// info = 31.
-static constexpr uint8_t kInitialByteIndefiniteLengthArray =
-    EncodeInitialByte(MajorType::ARRAY, 31);
-static constexpr uint8_t kInitialByteIndefiniteLengthMap =
-    EncodeInitialByte(MajorType::MAP, 31);
-// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
-// length maps / arrays.
-static constexpr uint8_t kStopByte =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
-
-}  // namespace cbor
-
 // The binary encoding for the inspector protocol follows the CBOR specification
 // (RFC 7049). Additional constraints:
 // - Only indefinite length maps and arrays are supported.
@@ -239,12 +154,38 @@
 //   as CBOR BYTE_STRING (major type 2). For such strings, the number of
 //   bytes encoded must be even.
 // - UTF8 strings (major type 3) are supported.
-// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not
+// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, never
 //   as UTF16 strings.
 // - Arbitrary byte arrays, in the inspector protocol called 'binary',
 //   are encoded as BYTE_STRING (major type 2), prefixed with a byte
 //   indicating base64 when rendered as JSON.
 
+// =============================================================================
+// Detecting CBOR content
+// =============================================================================
+
+// The first byte for an envelope, which we use for wrapping dictionaries
+// and arrays; and the byte that indicates a byte string with 32 bit length.
+// These two bytes start an envelope, and thereby also any CBOR message
+// produced or consumed by this protocol. See also |EnvelopeEncoder| below.
+uint8_t InitialByteForEnvelope();
+uint8_t InitialByteFor32BitLengthByteString();
+
+// Checks whether |msg| is a cbor message.
+bool IsCBORMessage(span<uint8_t> msg);
+
+// =============================================================================
+// Encoding individual CBOR items
+// =============================================================================
+
+// Some constants for CBOR tokens that only take a single byte on the wire.
+uint8_t EncodeTrue();
+uint8_t EncodeFalse();
+uint8_t EncodeNull();
+uint8_t EncodeIndefiniteLengthArrayStart();
+uint8_t EncodeIndefiniteLengthMapStart();
+uint8_t EncodeStop();
+
 // Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE|
 // (major type 1) iff < 0.
 void EncodeInt32(int32_t value, std::vector<uint8_t>* out);
@@ -275,13 +216,9 @@
 // with additional info = 27, followed by 8 bytes in big endian.
 void EncodeDouble(double value, std::vector<uint8_t>* out);
 
-// Some constants for CBOR tokens that only take a single byte on the wire.
-uint8_t EncodeTrue();
-uint8_t EncodeFalse();
-uint8_t EncodeNull();
-uint8_t EncodeIndefiniteLengthArrayStart();
-uint8_t EncodeIndefiniteLengthMapStart();
-uint8_t EncodeStop();
+// =============================================================================
+// cbor::EnvelopeEncoder - for wrapping submessages
+// =============================================================================
 
 // An envelope indicates the byte length of a wrapped item.
 // We use this for maps and array, which allows the decoder
@@ -304,20 +241,23 @@
   std::size_t byte_size_pos_ = 0;
 };
 
-// This can be used to convert from JSON to CBOR, by passing the
-// return value to the routines in json_parser.h.  The handler will encode into
-// |out|, and iff an error occurs it will set |status| to an error and clear
-// |out|. Otherwise, |status.ok()| will be |true|.
-std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder(
-    std::vector<uint8_t>* out, Status* status);
+// =============================================================================
+// cbor::NewCBOREncoder - for encoding from a streaming parser
+// =============================================================================
 
-// Parses a CBOR encoded message from |bytes|, sending JSON events to
-// |json_out|. If an error occurs, sends |out->HandleError|, and parsing stops.
-// The client is responsible for discarding the already received information in
-// that case.
-void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out);
+// This can be used to convert to CBOR, by passing the return value to a parser
+// that drives it. The handler will encode into |out|, and iff an error occurs
+// it will set |status| to an error and clear |out|. Otherwise, |status.ok()|
+// will be |true|.
+std::unique_ptr<StreamingParserHandler> NewCBOREncoder(
+    std::vector<uint8_t>* out,
+    Status* status);
 
-// Tags for the tokens within a CBOR message that CBORStream understands.
+// =============================================================================
+// cbor::CBORTokenizer - for parsing individual CBOR items
+// =============================================================================
+
+// Tags for the tokens within a CBOR message that CBORTokenizer understands.
 // Note that this is not the same terminology as the CBOR spec (RFC 7049),
 // but rather, our adaptation. For instance, we lump unsigned and signed
 // major type into INT32 here (and disallow values outside the int32_t range).
@@ -357,6 +297,18 @@
   DONE,
 };
 
+// The major types from RFC 7049 Section 2.1.
+enum class MajorType {
+  UNSIGNED = 0,
+  NEGATIVE = 1,
+  BYTE_STRING = 2,
+  STRING = 3,
+  ARRAY = 4,
+  MAP = 5,
+  TAG = 6,
+  SIMPLE_VALUE = 7
+};
+
 // CBORTokenizer segments a CBOR message, presenting the tokens therein as
 // numbers, strings, etc. This is not a complete CBOR parser, but makes it much
 // easier to implement one (e.g. ParseCBOR, above). It can also be used to parse
@@ -403,6 +355,9 @@
   // To be called only if ::TokenTag() == CBORTokenTag::BINARY.
   span<uint8_t> GetBinary() const;
 
+  // To be called only if ::TokenTag() == CBORTokenTag::ENVELOPE.
+  span<uint8_t> GetEnvelopeContents() const;
+
  private:
   void ReadNextToken(bool enter_envelope);
   void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length);
@@ -412,14 +367,70 @@
   CBORTokenTag token_tag_;
   struct Status status_;
   std::ptrdiff_t token_byte_length_;
-  cbor::MajorType token_start_type_;
+  MajorType token_start_type_;
   uint64_t token_start_internal_value_;
 };
 
-void DumpCBOR(span<uint8_t> cbor);
+// =============================================================================
+// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
+// =============================================================================
 
+// Parses a CBOR encoded message from |bytes|, sending events to
+// |out|. If an error occurs, sends |out->HandleError|, and parsing stops.
+// The client is responsible for discarding the already received information in
+// that case.
+void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out);
 
-{% for namespace in config.protocol.namespace %}
-} // namespace {{namespace}}
-{% endfor %}
-#endif // !defined({{"_".join(config.protocol.namespace)}}_CBOR_h)
+namespace internals {  // Exposed only for writing tests.
+int8_t ReadTokenStart(span<uint8_t> bytes,
+                      cbor::MajorType* type,
+                      uint64_t* value);
+
+void WriteTokenStart(cbor::MajorType type,
+                     uint64_t value,
+                     std::vector<uint8_t>* encoded);
+}  // namespace internals
+}  // namespace cbor
+
+namespace json {
+// Client code must provide an instance. Implementation should delegate
+// to whatever is appropriate.
+class Platform {
+ public:
+  virtual ~Platform() = default;
+  // Parses |str| into |result|. Returns false iff there are
+  // leftover characters or parsing errors.
+  virtual bool StrToD(const char* str, double* result) const = 0;
+
+  // Prints |value| in a format suitable for JSON.
+  virtual std::unique_ptr<char[]> DToStr(double value) const = 0;
+};
+
+// =============================================================================
+// json::NewJSONEncoder - for encoding streaming parser events as JSON
+// =============================================================================
+
+// Returns a handler object which will write ascii characters to |out|.
+// |status->ok()| will be false iff the handler routine HandleError() is called.
+// In that case, we'll stop emitting output.
+// Except for calling the HandleError routine at any time, the client
+// code must call the Handle* methods in an order in which they'd occur
+// in valid JSON; otherwise we may crash (the code uses assert).
+std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform,
+                                                       std::string* out,
+                                                       Status* status);
+
+// =============================================================================
+// json::ParseJSON - for receiving streaming parser events for JSON
+// =============================================================================
+
+void ParseJSON(const Platform* platform,
+               span<uint8_t> chars,
+               StreamingParserHandler* handler);
+void ParseJSON(const Platform* platform,
+               span<uint16_t> chars,
+               StreamingParserHandler* handler);
+}  // namespace json
+}  // namespace inspector_protocol_encoding
+
+#endif  // INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_
diff --git a/third_party/inspector_protocol/encoding/encoding_test.cc b/third_party/inspector_protocol/encoding/encoding_test.cc
new file mode 100644
index 0000000..6efe83d
--- /dev/null
+++ b/third_party/inspector_protocol/encoding/encoding_test.cc
@@ -0,0 +1,1595 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "encoding.h"
+
+#include <array>
+#include <clocale>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::ElementsAreArray;
+
+namespace inspector_protocol_encoding {
+
+std::string UTF16ToUTF8(span<uint16_t> in) {
+  std::string out;
+  bool success = base::UTF16ToUTF8(
+      reinterpret_cast<const base::char16*>(in.data()), in.size(), &out);
+  CHECK(success);
+  return out;
+}
+
+std::vector<uint16_t> UTF8ToUTF16(span<uint8_t> in) {
+  base::string16 tmp;
+  bool success = base::UTF8ToUTF16(reinterpret_cast<const char*>(in.data()),
+                                   in.size(), &tmp);
+  CHECK(success);
+  return std::vector<uint16_t>(tmp.begin(), tmp.end());
+}
+
+class TestPlatform : public json::Platform {
+  bool StrToD(const char* str, double* result) const override {
+    // This is not thread-safe
+    // (see https://en.cppreference.com/w/cpp/locale/setlocale)
+    // but good enough for a unittest.
+    const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr);
+    char* end;
+    *result = std::strtod(str, &end);
+    std::setlocale(LC_NUMERIC, saved_locale);
+    if (errno == ERANGE) {
+      // errno must be reset, e.g. see the example here:
+      // https://en.cppreference.com/w/cpp/string/byte/strtof
+      errno = 0;
+      return false;
+    }
+    return end == str + strlen(str);
+  }
+
+  std::unique_ptr<char[]> DToStr(double value) const override {
+    std::stringstream ss;
+    ss.imbue(std::locale("C"));
+    ss << value;
+    std::string str = ss.str();
+    std::unique_ptr<char[]> result(new char[str.size() + 1]);
+    memcpy(result.get(), str.c_str(), str.size() + 1);
+    return result;
+  }
+};
+
+json::Platform* GetTestPlatform() {
+  static TestPlatform* platform = new TestPlatform;
+  return platform;
+}
+
+// =============================================================================
+// span - sequence of bytes
+// =============================================================================
+
+template <typename T>
+class SpanTest : public ::testing::Test {};
+
+using TestTypes = ::testing::Types<uint8_t, uint16_t>;
+TYPED_TEST_SUITE(SpanTest, TestTypes);
+
+TYPED_TEST(SpanTest, Empty) {
+  span<TypeParam> empty;
+  EXPECT_TRUE(empty.empty());
+  EXPECT_EQ(0, empty.size());
+  EXPECT_EQ(0, empty.size_bytes());
+  EXPECT_EQ(empty.begin(), empty.end());
+}
+
+TYPED_TEST(SpanTest, SingleItem) {
+  TypeParam single_item = 42;
+  span<TypeParam> singular(&single_item, 1);
+  EXPECT_FALSE(singular.empty());
+  EXPECT_EQ(1, singular.size());
+  EXPECT_EQ(sizeof(TypeParam), static_cast<size_t>(singular.size_bytes()));
+  EXPECT_EQ(singular.begin() + 1, singular.end());
+  EXPECT_EQ(42, singular[0]);
+}
+
+TYPED_TEST(SpanTest, FiveItems) {
+  std::vector<TypeParam> test_input = {31, 32, 33, 34, 35};
+  span<TypeParam> five_items(test_input.data(), 5);
+  EXPECT_FALSE(five_items.empty());
+  EXPECT_EQ(5, five_items.size());
+  EXPECT_EQ(sizeof(TypeParam) * 5,
+            static_cast<size_t>(five_items.size_bytes()));
+  EXPECT_EQ(five_items.begin() + 5, five_items.end());
+  EXPECT_EQ(31, five_items[0]);
+  EXPECT_EQ(32, five_items[1]);
+  EXPECT_EQ(33, five_items[2]);
+  EXPECT_EQ(34, five_items[3]);
+  EXPECT_EQ(35, five_items[4]);
+  span<TypeParam> three_items = five_items.subspan(2);
+  EXPECT_EQ(3, three_items.size());
+  EXPECT_EQ(33, three_items[0]);
+  EXPECT_EQ(34, three_items[1]);
+  EXPECT_EQ(35, three_items[2]);
+  span<TypeParam> two_items = five_items.subspan(2, 2);
+  EXPECT_EQ(2, two_items.size());
+  EXPECT_EQ(33, two_items[0]);
+  EXPECT_EQ(34, two_items[1]);
+}
+
+namespace cbor {
+
+// =============================================================================
+// Detecting CBOR content
+// =============================================================================
+
+TEST(IsCBORMessage, SomeSmokeTests) {
+  std::vector<uint8_t> empty;
+  EXPECT_FALSE(IsCBORMessage(SpanFromVector(empty)));
+  std::vector<uint8_t> hello = {'H', 'e', 'l', 'o', ' ', 't',
+                                'h', 'e', 'r', 'e', '!'};
+  EXPECT_FALSE(IsCBORMessage(SpanFromVector(hello)));
+  std::vector<uint8_t> example = {0xd8, 0x5a, 0, 0, 0, 0};
+  EXPECT_TRUE(IsCBORMessage(SpanFromVector(example)));
+  std::vector<uint8_t> one = {0xd8, 0x5a, 0, 0, 0, 1, 1};
+  EXPECT_TRUE(IsCBORMessage(SpanFromVector(one)));
+}
+
+// =============================================================================
+// Encoding individual CBOR items
+// cbor::CBORTokenizer - for parsing individual CBOR items
+// =============================================================================
+
+//
+// EncodeInt32 / CBORTokenTag::INT32
+//
+TEST(EncodeDecodeInt32Test, Roundtrips23) {
+  // This roundtrips the int32_t value 23 through the pair of EncodeInt32 /
+  // CBORTokenizer; this is interesting since 23 is encoded as a single byte.
+  std::vector<uint8_t> encoded;
+  EncodeInt32(23, &encoded);
+  // first three bits: major type = 0; remaining five bits: additional info =
+  // value 23.
+  EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{23}}));
+
+  // Reverse direction: decode with CBORTokenizer.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
+  EXPECT_EQ(23, tokenizer.GetInt32());
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeInt32Test, RoundtripsUint8) {
+  // This roundtrips the int32_t value 42 through the pair of EncodeInt32 /
+  // CBORTokenizer. This is different from Roundtrip23 because 42 is encoded
+  // in an extra byte after the initial one.
+  std::vector<uint8_t> encoded;
+  EncodeInt32(42, &encoded);
+  // first three bits: major type = 0;
+  // remaining five bits: additional info = 24, indicating payload is uint8.
+  EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 2>{{24, 42}}));
+
+  // Reverse direction: decode with CBORTokenizer.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
+  EXPECT_EQ(42, tokenizer.GetInt32());
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeInt32Test, RoundtripsUint16) {
+  // 500 is encoded as a uint16 after the initial byte.
+  std::vector<uint8_t> encoded;
+  EncodeInt32(500, &encoded);
+  // 1 for initial byte, 2 for uint16.
+  EXPECT_EQ(static_cast<std::size_t>(3), encoded.size());
+  // first three bits: major type = 0;
+  // remaining five bits: additional info = 25, indicating payload is uint16.
+  EXPECT_EQ(25, encoded[0]);
+  EXPECT_EQ(0x01, encoded[1]);
+  EXPECT_EQ(0xf4, encoded[2]);
+
+  // Reverse direction: decode with CBORTokenizer.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
+  EXPECT_EQ(500, tokenizer.GetInt32());
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) {
+  // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte.
+  std::vector<uint8_t> encoded;
+  EncodeInt32(std::numeric_limits<int32_t>::max(), &encoded);
+  // 1 for initial byte, 4 for the uint32.
+  // first three bits: major type = 0;
+  // remaining five bits: additional info = 26, indicating payload is uint32.
+  EXPECT_THAT(
+      encoded,
+      ElementsAreArray(std::array<uint8_t, 5>{{26, 0x7f, 0xff, 0xff, 0xff}}));
+
+  // Reverse direction: decode with CBORTokenizer.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
+  EXPECT_EQ(std::numeric_limits<int32_t>::max(), tokenizer.GetInt32());
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeInt32Test, CantRoundtripUint32) {
+  // 0xdeadbeef is a value which does not fit below
+  // std::numerical_limits<int32_t>::max(), so we can't encode
+  // it with EncodeInt32. However, CBOR does support this, so we
+  // encode it here manually with the internal routine, just to observe
+  // that it's considered an invalid int32 by CBORTokenizer.
+  std::vector<uint8_t> encoded;
+  internals::WriteTokenStart(MajorType::UNSIGNED, 0xdeadbeef, &encoded);
+  // 1 for initial byte, 4 for the uint32.
+  // first three bits: major type = 0;
+  // remaining five bits: additional info = 26, indicating payload is uint32.
+  EXPECT_THAT(
+      encoded,
+      ElementsAreArray(std::array<uint8_t, 5>{{26, 0xde, 0xad, 0xbe, 0xef}}));
+
+  // Now try to decode; we treat this as an invalid INT32.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  // 0xdeadbeef is > std::numerical_limits<int32_t>::max().
+  EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
+  EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error);
+}
+
+TEST(EncodeDecodeInt32Test, DecodeErrorCases) {
+  struct TestCase {
+    std::vector<uint8_t> data;
+    std::string msg;
+  };
+  std::vector<TestCase> tests{
+      {TestCase{
+           {24},
+           "additional info = 24 would require 1 byte of payload (but it's 0)"},
+       TestCase{{27, 0xaa, 0xbb, 0xcc},
+                "additional info = 27 would require 8 bytes of payload (but "
+                "it's 3)"},
+       TestCase{{29}, "additional info = 29 isn't recognized"}}};
+
+  for (const TestCase& test : tests) {
+    SCOPED_TRACE(test.msg);
+    CBORTokenizer tokenizer(SpanFromVector(test.data));
+    EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
+    EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error);
+  }
+}
+
+TEST(EncodeDecodeInt32Test, RoundtripsMinus24) {
+  // This roundtrips the int32_t value -24 through the pair of EncodeInt32 /
+  // CBORTokenizer; this is interesting since -24 is encoded as
+  // a single byte as NEGATIVE, and it tests the specific encoding
+  // (note how for unsigned the single byte covers values up to 23).
+  // Additional examples are covered in RoundtripsAdditionalExamples.
+  std::vector<uint8_t> encoded;
+  EncodeInt32(-24, &encoded);
+  // first three bits: major type = 1; remaining five bits: additional info =
+  // value 23.
+  EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{1 << 5 | 23}}));
+
+  // Reverse direction: decode with CBORTokenizer.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
+  EXPECT_EQ(-24, tokenizer.GetInt32());
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeInt32Test, RoundtripsAdditionalNegativeExamples) {
+  std::vector<int32_t> examples = {-1,
+                                   -10,
+                                   -24,
+                                   -25,
+                                   -300,
+                                   -30000,
+                                   -300 * 1000,
+                                   -1000 * 1000,
+                                   -1000 * 1000 * 1000,
+                                   std::numeric_limits<int32_t>::min()};
+  for (int32_t example : examples) {
+    SCOPED_TRACE(std::string("example ") + std::to_string(example));
+    std::vector<uint8_t> encoded;
+    EncodeInt32(example, &encoded);
+    CBORTokenizer tokenizer(SpanFromVector(encoded));
+    EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
+    EXPECT_EQ(example, tokenizer.GetInt32());
+    tokenizer.Next();
+    EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+  }
+}
+
+//
+// EncodeString16 / CBORTokenTag::STRING16
+//
+TEST(EncodeDecodeString16Test, RoundtripsEmpty) {
+  // This roundtrips the empty utf16 string through the pair of EncodeString16 /
+  // CBORTokenizer.
+  std::vector<uint8_t> encoded;
+  EncodeString16(span<uint16_t>(), &encoded);
+  EXPECT_EQ(static_cast<std::size_t>(1), encoded.size());
+  // first three bits: major type = 2; remaining five bits: additional info =
+  // size 0.
+  EXPECT_EQ(2 << 5, encoded[0]);
+
+  // Reverse direction: decode with CBORTokenizer.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
+  span<uint8_t> decoded_string16_wirerep = tokenizer.GetString16WireRep();
+  EXPECT_TRUE(decoded_string16_wirerep.empty());
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+// On the wire, we STRING16 is encoded as little endian (least
+// significant byte first). The host may or may not be little endian,
+// so this routine follows the advice in
+// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html.
+std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) {
+  CHECK_EQ(in.size() & 1, 0);  // must be even number of bytes.
+  std::vector<uint16_t> host_out;
+  for (std::ptrdiff_t ii = 0; ii < in.size(); ii += 2)
+    host_out.push_back(in[ii + 1] << 8 | in[ii]);
+  return host_out;
+}
+
+TEST(EncodeDecodeString16Test, RoundtripsHelloWorld) {
+  // This roundtrips the hello world message which is given here in utf16
+  // characters. 0xd83c, 0xdf0e: UTF16 encoding for the "Earth Globe Americas"
+  // character, 🌎.
+  std::array<uint16_t, 10> msg{
+      {'H', 'e', 'l', 'l', 'o', ',', ' ', 0xd83c, 0xdf0e, '.'}};
+  std::vector<uint8_t> encoded;
+  EncodeString16(span<uint16_t>(msg.data(), msg.size()), &encoded);
+  // This will be encoded as BYTE_STRING of length 20, so the 20 is encoded in
+  // the additional info part of the initial byte. Payload is two bytes for each
+  // UTF16 character.
+  uint8_t initial_byte = /*major type=*/2 << 5 | /*additional info=*/20;
+  std::array<uint8_t, 21> encoded_expected = {
+      {initial_byte, 'H', 0,   'e', 0,    'l',  0,    'l',  0,   'o', 0,
+       ',',          0,   ' ', 0,   0x3c, 0xd8, 0x0e, 0xdf, '.', 0}};
+  EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
+
+  // Now decode to complete the roundtrip.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
+  std::vector<uint16_t> decoded =
+      String16WireRepToHost(tokenizer.GetString16WireRep());
+  EXPECT_THAT(decoded, ElementsAreArray(msg));
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+
+  // For bonus points, we look at the decoded message in UTF8 as well so we can
+  // easily see it on the terminal screen.
+  std::string utf8_decoded = UTF16ToUTF8(SpanFromVector(decoded));
+  EXPECT_EQ("Hello, 🌎.", utf8_decoded);
+}
+
+TEST(EncodeDecodeString16Test, Roundtrips500) {
+  // We roundtrip a message that has 250 16 bit values. Each of these are just
+  // set to their index. 250 is interesting because the cbor spec uses a
+  // BYTE_STRING of length 500 for one of their examples of how to encode the
+  // start of it (section 2.1) so it's easy for us to look at the first three
+  // bytes closely.
+  std::vector<uint16_t> two_fifty;
+  for (uint16_t ii = 0; ii < 250; ++ii)
+    two_fifty.push_back(ii);
+  std::vector<uint8_t> encoded;
+  EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded);
+  EXPECT_EQ(static_cast<std::size_t>(3 + 250 * 2), encoded.size());
+  // Now check the first three bytes:
+  // Major type: 2 (BYTE_STRING)
+  // Additional information: 25, indicating size is represented by 2 bytes.
+  // Bytes 1 and 2 encode 500 (0x01f4).
+  EXPECT_EQ(2 << 5 | 25, encoded[0]);
+  EXPECT_EQ(0x01, encoded[1]);
+  EXPECT_EQ(0xf4, encoded[2]);
+
+  // Now decode to complete the roundtrip.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
+  std::vector<uint16_t> decoded =
+      String16WireRepToHost(tokenizer.GetString16WireRep());
+  EXPECT_THAT(decoded, ElementsAreArray(two_fifty));
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeString16Test, ErrorCases) {
+  struct TestCase {
+    std::vector<uint8_t> data;
+    std::string msg;
+  };
+  std::vector<TestCase> tests{
+      {TestCase{{2 << 5 | 1, 'a'},
+                "length must be divisible by 2 (but it's 1)"},
+       TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"}}};
+  for (const TestCase& test : tests) {
+    SCOPED_TRACE(test.msg);
+    CBORTokenizer tokenizer(SpanFromVector(test.data));
+    EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
+    EXPECT_EQ(Error::CBOR_INVALID_STRING16, tokenizer.Status().error);
+  }
+}
+
+//
+// EncodeString8 / CBORTokenTag::STRING8
+//
+TEST(EncodeDecodeString8Test, RoundtripsHelloWorld) {
+  // This roundtrips the hello world message which is given here in utf8
+  // characters. 🌎 is a four byte utf8 character.
+  std::string utf8_msg = "Hello, 🌎.";
+  std::vector<uint8_t> msg(utf8_msg.begin(), utf8_msg.end());
+  std::vector<uint8_t> encoded;
+  EncodeString8(SpanFromStdString(utf8_msg), &encoded);
+  // This will be encoded as STRING of length 12, so the 12 is encoded in
+  // the additional info part of the initial byte. Payload is one byte per
+  // utf8 byte.
+  uint8_t initial_byte = /*major type=*/3 << 5 | /*additional info=*/12;
+  std::array<uint8_t, 13> encoded_expected = {{initial_byte, 'H', 'e', 'l', 'l',
+                                               'o', ',', ' ', 0xF0, 0x9f, 0x8c,
+                                               0x8e, '.'}};
+  EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
+
+  // Now decode to complete the roundtrip.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
+  std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
+                               tokenizer.GetString8().end());
+  EXPECT_THAT(decoded, ElementsAreArray(msg));
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) {
+  std::vector<std::pair<std::string, std::string>> examples = {
+      {"Hello, world.", "Hello, world."},
+      {"Above: \xDC"
+       "ber",
+       "Above: Über"},
+      {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF",
+       "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}};
+
+  for (const auto& example : examples) {
+    const std::string& latin1 = example.first;
+    const std::string& expected_utf8 = example.second;
+    std::vector<uint8_t> encoded;
+    EncodeFromLatin1(SpanFromStdString(latin1), &encoded);
+    CBORTokenizer tokenizer(SpanFromVector(encoded));
+    EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
+    std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
+                                 tokenizer.GetString8().end());
+    std::string decoded_str(decoded.begin(), decoded.end());
+    EXPECT_THAT(decoded_str, testing::Eq(expected_utf8));
+  }
+}
+
+TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) {
+  std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'};
+  std::vector<uint8_t> encoded;
+  EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded);
+
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
+  std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
+                               tokenizer.GetString8().end());
+  std::string decoded_str(decoded.begin(), decoded.end());
+  EXPECT_THAT(decoded_str, testing::Eq("easy"));
+}
+
+TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) {
+  // Since this message contains non-ASCII characters, the routine is
+  // forced to encode as UTF16. We see this below by checking that the
+  // token tag is STRING16.
+  std::vector<uint16_t> msg = {'H', 'e', 'l',    'l',    'o',
+                               ',', ' ', 0xd83c, 0xdf0e, '.'};
+  std::vector<uint8_t> encoded;
+  EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded);
+
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
+  std::vector<uint16_t> decoded =
+      String16WireRepToHost(tokenizer.GetString16WireRep());
+  std::string utf8_decoded = UTF16ToUTF8(SpanFromVector(decoded));
+  EXPECT_EQ("Hello, 🌎.", utf8_decoded);
+}
+
+//
+// EncodeBinary / CBORTokenTag::BINARY
+//
+TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) {
+  std::vector<uint8_t> binary = {'H', 'e', 'l', 'l', 'o', ',', ' ',
+                                 'w', 'o', 'r', 'l', 'd', '.'};
+  std::vector<uint8_t> encoded;
+  EncodeBinary(span<uint8_t>(binary.data(), binary.size()), &encoded);
+  // So, on the wire we see that the binary blob travels unmodified.
+  EXPECT_THAT(
+      encoded,
+      ElementsAreArray(std::array<uint8_t, 15>{
+          {(6 << 5 | 22),  // tag 22 indicating base64 interpretation in JSON
+           (2 << 5 | 13),  // BYTE_STRING (type 2) of length 13
+           'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}}));
+  std::vector<uint8_t> decoded;
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag());
+  EXPECT_EQ(0, int(tokenizer.Status().error));
+  decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(),
+                                 tokenizer.GetBinary().end());
+  EXPECT_THAT(decoded, ElementsAreArray(binary));
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+//
+// EncodeDouble / CBORTokenTag::DOUBLE
+//
+TEST(EncodeDecodeDoubleTest, RoundtripsWikipediaExample) {
+  // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+  // provides the example of a hex representation 3FD5 5555 5555 5555, which
+  // approximates 1/3.
+
+  const double kOriginalValue = 1.0 / 3;
+  std::vector<uint8_t> encoded;
+  EncodeDouble(kOriginalValue, &encoded);
+  // first three bits: major type = 7; remaining five bits: additional info =
+  // value 27. This is followed by 8 bytes of payload (which match Wikipedia).
+  EXPECT_THAT(
+      encoded,
+      ElementsAreArray(std::array<uint8_t, 9>{
+          {7 << 5 | 27, 0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}}));
+
+  // Reverse direction: decode and compare with original value.
+  CBORTokenizer tokenizer(SpanFromVector(encoded));
+  EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
+  EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(kOriginalValue));
+  tokenizer.Next();
+  EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+}
+
+TEST(EncodeDecodeDoubleTest, RoundtripsAdditionalExamples) {
+  std::vector<double> examples = {0.0,
+                                  1.0,
+                                  -1.0,
+                                  3.1415,
+                                  std::numeric_limits<double>::min(),
+                                  std::numeric_limits<double>::max(),
+                                  std::numeric_limits<double>::infinity(),
+                                  std::numeric_limits<double>::quiet_NaN()};
+  for (double example : examples) {
+    SCOPED_TRACE(std::string("example ") + std::to_string(example));
+    std::vector<uint8_t> encoded;
+    EncodeDouble(example, &encoded);
+    CBORTokenizer tokenizer(SpanFromVector(encoded));
+    EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
+    if (std::isnan(example))
+      EXPECT_TRUE(std::isnan(tokenizer.GetDouble()));
+    else
+      EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(example));
+    tokenizer.Next();
+    EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
+  }
+}
+
+// =============================================================================
+// cbor::NewCBOREncoder - for encoding from a streaming parser
+// =============================================================================
+
+void EncodeUTF8ForTest(const std::string& key, std::vector<uint8_t>* out) {
+  EncodeString8(SpanFromStdString(key), out);
+}
+TEST(JSONToCBOREncoderTest, SevenBitStrings) {
+  // When a string can be represented as 7 bit ASCII, the encoder will use the
+  // STRING (major Type 3) type, so the actual characters end up as bytes on the
+  // wire.
+  std::vector<uint8_t> encoded;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> encoder =
+      NewCBOREncoder(&encoded, &status);
+  std::vector<uint16_t> utf16 = {'f', 'o', 'o'};
+  encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size()));
+  EXPECT_EQ(Error::OK, status.error);
+  // Here we assert that indeed, seven bit strings are represented as
+  // bytes on the wire, "foo" is just "foo".
+  EXPECT_THAT(encoded,
+              ElementsAreArray(std::array<uint8_t, 4>{
+                  {/*major type 3*/ 3 << 5 | /*length*/ 3, 'f', 'o', 'o'}}));
+}
+
+TEST(JsonCborRoundtrip, EncodingDecoding) {
+  // Hits all the cases except binary and error in StreamingParserHandler, first
+  // parsing a JSON message into CBOR, then parsing it back from CBOR into JSON.
+  std::string json =
+      "{"
+      "\"string\":\"Hello, \\ud83c\\udf0e.\","
+      "\"double\":3.1415,"
+      "\"int\":1,"
+      "\"negative int\":-1,"
+      "\"bool\":true,"
+      "\"null\":null,"
+      "\"array\":[1,2,3]"
+      "}";
+  std::vector<uint8_t> encoded;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> encoder =
+      NewCBOREncoder(&encoded, &status);
+  span<uint8_t> ascii_in = SpanFromStdString(json);
+  json::ParseJSON(GetTestPlatform(), ascii_in, encoder.get());
+  std::vector<uint8_t> expected = {
+      0xd8,            // envelope
+      0x5a,            // byte string with 32 bit length
+      0,    0, 0, 94,  // length is 94 bytes
+  };
+  expected.push_back(0xbf);  // indef length map start
+  EncodeString8(SpanFromStdString("string"), &expected);
+  // This is followed by the encoded string for "Hello, 🌎."
+  // So, it's the same bytes that we tested above in
+  // EncodeDecodeString16Test.RoundtripsHelloWorld.
+  expected.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
+  for (uint8_t ch : std::array<uint8_t, 20>{
+           {'H', 0, 'e', 0, 'l',  0,    'l',  0,    'o', 0,
+            ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
+    expected.push_back(ch);
+  EncodeString8(SpanFromStdString("double"), &expected);
+  EncodeDouble(3.1415, &expected);
+  EncodeString8(SpanFromStdString("int"), &expected);
+  EncodeInt32(1, &expected);
+  EncodeString8(SpanFromStdString("negative int"), &expected);
+  EncodeInt32(-1, &expected);
+  EncodeString8(SpanFromStdString("bool"), &expected);
+  expected.push_back(7 << 5 | 21);  // RFC 7049 Section 2.3, Table 2: true
+  EncodeString8(SpanFromStdString("null"), &expected);
+  expected.push_back(7 << 5 | 22);  // RFC 7049 Section 2.3, Table 2: null
+  EncodeString8(SpanFromStdString("array"), &expected);
+  expected.push_back(0xd8);  // envelope
+  expected.push_back(0x5a);  // byte string with 32 bit length
+  // the length is 5 bytes (that's up to end indef length array below).
+  for (uint8_t ch : std::array<uint8_t, 4>{{0, 0, 0, 5}})
+    expected.push_back(ch);
+  expected.push_back(0x9f);  // RFC 7049 Section 2.2.1, indef length array start
+  expected.push_back(1);     // Three UNSIGNED values (easy since Major Type 0)
+  expected.push_back(2);
+  expected.push_back(3);
+  expected.push_back(0xff);  // End indef length array
+  expected.push_back(0xff);  // End indef length map
+  EXPECT_TRUE(status.ok());
+  EXPECT_THAT(encoded, ElementsAreArray(expected));
+
+  // And now we roundtrip, decoding the message we just encoded.
+  std::string decoded;
+  std::unique_ptr<StreamingParserHandler> json_encoder =
+      NewJSONEncoder(GetTestPlatform(), &decoded, &status);
+  ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_encoder.get());
+  EXPECT_EQ(Error::OK, status.error);
+  EXPECT_EQ(json, decoded);
+}
+
+TEST(JsonCborRoundtrip, MoreRoundtripExamples) {
+  std::vector<std::string> examples = {
+      // Tests that after closing a nested objects, additional key/value pairs
+      // are considered.
+      "{\"foo\":{\"bar\":1},\"baz\":2}", "{\"foo\":[1,2,3],\"baz\":2}"};
+  for (const std::string& json : examples) {
+    SCOPED_TRACE(std::string("example: ") + json);
+    std::vector<uint8_t> encoded;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> encoder =
+        NewCBOREncoder(&encoded, &status);
+    span<uint8_t> ascii_in = SpanFromStdString(json);
+    ParseJSON(GetTestPlatform(), ascii_in, encoder.get());
+    std::string decoded;
+    std::unique_ptr<StreamingParserHandler> json_writer =
+        NewJSONEncoder(GetTestPlatform(), &decoded, &status);
+    ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
+    EXPECT_EQ(Error::OK, status.error);
+    EXPECT_EQ(json, decoded);
+  }
+}
+
+TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) {
+  // The StreamingParserHandler::HandleBinary is a special case: The JSON parser
+  // will never call this method, because JSON does not natively support the
+  // binary type. So, we can't fully roundtrip. However, the other direction
+  // works: binary will be rendered in JSON, as a base64 string. So, we make
+  // calls to the encoder directly here, to construct a message, and one of
+  // these calls is ::HandleBinary, to which we pass a "binary" string
+  // containing "Hello, world.".
+  std::vector<uint8_t> encoded;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> encoder =
+      NewCBOREncoder(&encoded, &status);
+  encoder->HandleMapBegin();
+  // Emit a key.
+  std::vector<uint16_t> key = {'f', 'o', 'o'};
+  encoder->HandleString16(SpanFromVector(key));
+  // Emit the binary payload, an arbitrary array of bytes that happens to
+  // be the ascii message "Hello, world.".
+  encoder->HandleBinary(SpanFromVector(std::vector<uint8_t>{
+      'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}));
+  encoder->HandleMapEnd();
+  EXPECT_EQ(Error::OK, status.error);
+
+  // Now drive the json writer via the CBOR decoder.
+  std::string decoded;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &decoded, &status);
+  ParseCBOR(SpanFromVector(encoded), json_writer.get());
+  EXPECT_EQ(Error::OK, status.error);
+  EXPECT_EQ(Status::npos(), status.pos);
+  // "Hello, world." in base64 is "SGVsbG8sIHdvcmxkLg==".
+  EXPECT_EQ("{\"foo\":\"SGVsbG8sIHdvcmxkLg==\"}", decoded);
+}
+
+// =============================================================================
+// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
+// =============================================================================
+
+TEST(ParseCBORTest, ParseEmptyCBORMessage) {
+  // An envelope starting with 0xd8, 0x5a, with the byte length
+  // of 2, containing a map that's empty (0xbf for map
+  // start, and 0xff for map end).
+  std::vector<uint8_t> in = {0xd8, 0x5a, 0, 0, 0, 2, 0xbf, 0xff};
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
+  EXPECT_EQ(Error::OK, status.error);
+  EXPECT_EQ("{}", out);
+}
+
+TEST(ParseCBORTest, ParseCBORHelloWorld) {
+  const uint8_t kPayloadLen = 27;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen};
+  bytes.push_back(0xbf);                            // start indef length map.
+  EncodeString8(SpanFromStdString("msg"), &bytes);  // key: msg
+  // Now write the value, the familiar "Hello, 🌎." where the globe is expressed
+  // as two utf16 chars.
+  bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
+  for (uint8_t ch : std::array<uint8_t, 20>{
+           {'H', 0, 'e', 0, 'l',  0,    'l',  0,    'o', 0,
+            ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
+    bytes.push_back(ch);
+  bytes.push_back(0xff);  // stop byte
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::OK, status.error);
+  EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out);
+}
+
+TEST(ParseCBORTest, UTF8IsSupportedInKeys) {
+  const uint8_t kPayloadLen = 11;
+  std::vector<uint8_t> bytes = {cbor::InitialByteForEnvelope(),
+                                cbor::InitialByteFor32BitLengthByteString(),
+                                0,
+                                0,
+                                0,
+                                kPayloadLen};
+  bytes.push_back(cbor::EncodeIndefiniteLengthMapStart());
+  // Two UTF16 chars.
+  EncodeString8(SpanFromStdString("🌎"), &bytes);
+  // Can be encoded as a single UTF16 char.
+  EncodeString8(SpanFromStdString("☾"), &bytes);
+  bytes.push_back(cbor::EncodeStop());
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::OK, status.error);
+  EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out);
+}
+
+TEST(ParseCBORTest, NoInputError) {
+  std::vector<uint8_t> in = {};
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_NO_INPUT, status.error);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidStartByteError) {
+  // Here we test that some actual json, which usually starts with {,
+  // is not considered CBOR. CBOR messages must start with 0x5a, the
+  // envelope start byte.
+  std::string json = "{\"msg\": \"Hello, world.\"}";
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(SpanFromStdString(json), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
+  constexpr uint8_t kPayloadLen = 5;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  // A key; so value would be next.
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error);
+  EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, UnexpectedEofInArrayError) {
+  constexpr uint8_t kPayloadLen = 8;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};  // The byte for starting a map.
+  // A key; so value would be next.
+  EncodeString8(SpanFromStdString("array"), &bytes);
+  bytes.push_back(0x9f);  // byte for indefinite length array start.
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error);
+  EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, UnexpectedEofInMapError) {
+  constexpr uint8_t kPayloadLen = 1;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};  // The byte for starting a map.
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error);
+  EXPECT_EQ(7, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidMapKeyError) {
+  constexpr uint8_t kPayloadLen = 2;
+  std::vector<uint8_t> bytes = {0xd8,       0x5a, 0,
+                                0,          0,    kPayloadLen,  // envelope
+                                0xbf,                           // map start
+                                7 << 5 | 22};  // null (not a valid map key)
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error);
+  EXPECT_EQ(7, status.pos);
+  EXPECT_EQ("", out);
+}
+
+std::vector<uint8_t> MakeNestedCBOR(int depth) {
+  std::vector<uint8_t> bytes;
+  std::vector<EnvelopeEncoder> envelopes;
+  for (int ii = 0; ii < depth; ++ii) {
+    envelopes.emplace_back();
+    envelopes.back().EncodeStart(&bytes);
+    bytes.push_back(0xbf);  // indef length map start
+    EncodeString8(SpanFromStdString("key"), &bytes);
+  }
+  EncodeString8(SpanFromStdString("innermost_value"), &bytes);
+  for (int ii = 0; ii < depth; ++ii) {
+    bytes.push_back(0xff);  // stop byte, finishes map.
+    envelopes.back().EncodeStop(&bytes);
+    envelopes.pop_back();
+  }
+  return bytes;
+}
+
+TEST(ParseCBORTest, StackLimitExceededError) {
+  {  // Depth 3: no stack limit exceeded error and is easy to inspect.
+    std::vector<uint8_t> bytes = MakeNestedCBOR(3);
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> json_writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+    EXPECT_EQ(Error::OK, status.error);
+    EXPECT_EQ(Status::npos(), status.pos);
+    EXPECT_EQ("{\"key\":{\"key\":{\"key\":\"innermost_value\"}}}", out);
+  }
+  {  // Depth 1000: no stack limit exceeded.
+    std::vector<uint8_t> bytes = MakeNestedCBOR(1000);
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> json_writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+    EXPECT_EQ(Error::OK, status.error);
+    EXPECT_EQ(Status::npos(), status.pos);
+  }
+
+  // We just want to know the length of one opening map so we can compute
+  // where the error is encountered. So we look at a small example and find
+  // the second envelope start.
+  std::vector<uint8_t> small_example = MakeNestedCBOR(3);
+  int64_t opening_segment_size = 1;  // Start after the first envelope start.
+  while (opening_segment_size < static_cast<int64_t>(small_example.size()) &&
+         small_example[opening_segment_size] != 0xd8)
+    opening_segment_size++;
+
+  {  // Depth 1001: limit exceeded.
+    std::vector<uint8_t> bytes = MakeNestedCBOR(1001);
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> json_writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+    EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
+    EXPECT_EQ(opening_segment_size * 1001, status.pos);
+  }
+  {  // Depth 1200: still limit exceeded, and at the same pos as for 1001
+    std::vector<uint8_t> bytes = MakeNestedCBOR(1200);
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> json_writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+    EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
+    EXPECT_EQ(opening_segment_size * 1001, status.pos);
+  }
+}
+
+TEST(ParseCBORTest, UnsupportedValueError) {
+  constexpr uint8_t kPayloadLen = 6;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  int64_t error_pos = bytes.size();
+  bytes.push_back(6 << 5 | 5);  // tags aren't supported yet.
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidString16Error) {
+  constexpr uint8_t kPayloadLen = 11;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  int64_t error_pos = bytes.size();
+  // a BYTE_STRING of length 5 as value; since we interpret these as string16,
+  // it's going to be invalid as each character would need two bytes, but
+  // 5 isn't divisible by 2.
+  bytes.push_back(2 << 5 | 5);
+  for (int ii = 0; ii < 5; ++ii)
+    bytes.push_back(' ');
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidString8Error) {
+  constexpr uint8_t kPayloadLen = 6;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  int64_t error_pos = bytes.size();
+  // a STRING of length 5 as value, but we're at the end of the bytes array
+  // so it can't be decoded successfully.
+  bytes.push_back(3 << 5 | 5);
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidBinaryError) {
+  constexpr uint8_t kPayloadLen = 9;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  int64_t error_pos = bytes.size();
+  bytes.push_back(6 << 5 | 22);  // base64 hint for JSON; indicates binary
+  bytes.push_back(2 << 5 | 10);  // BYTE_STRING (major type 2) of length 10
+  // Just two garbage bytes, not enough for the binary.
+  bytes.push_back(0x31);
+  bytes.push_back(0x23);
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidDoubleError) {
+  constexpr uint8_t kPayloadLen = 8;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  int64_t error_pos = bytes.size();
+  bytes.push_back(7 << 5 | 27);  // initial byte for double
+  // Just two garbage bytes, not enough to represent an actual double.
+  bytes.push_back(0x31);
+  bytes.push_back(0x23);
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, InvalidSignedError) {
+  constexpr uint8_t kPayloadLen = 14;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  int64_t error_pos = bytes.size();
+  // uint64_t max is a perfectly fine value to encode as CBOR unsigned,
+  // but we don't support this since we only cover the int32_t range.
+  internals::WriteTokenStart(MajorType::UNSIGNED,
+                             std::numeric_limits<uint64_t>::max(), &bytes);
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+
+TEST(ParseCBORTest, TrailingJunk) {
+  constexpr uint8_t kPayloadLen = 35;
+  std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
+                                0xbf};                             // map start
+  EncodeString8(SpanFromStdString("key"), &bytes);
+  EncodeString8(SpanFromStdString("value"), &bytes);
+  bytes.push_back(0xff);  // Up to here, it's a perfectly fine msg.
+  int64_t error_pos = bytes.size();
+  EncodeString8(SpanFromStdString("trailing junk"), &bytes);
+
+  internals::WriteTokenStart(MajorType::UNSIGNED,
+                             std::numeric_limits<uint64_t>::max(), &bytes);
+  EXPECT_EQ(kPayloadLen, bytes.size() - 6);
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> json_writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
+  EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error);
+  EXPECT_EQ(error_pos, status.pos);
+  EXPECT_EQ("", out);
+}
+}  // namespace cbor
+
+namespace json {
+
+// =============================================================================
+// json::NewJSONEncoder - for encoding streaming parser events as JSON
+// =============================================================================
+
+void WriteUTF8AsUTF16(StreamingParserHandler* writer, const std::string& utf8) {
+  writer->HandleString16(SpanFromVector(UTF8ToUTF16(SpanFromStdString(utf8))));
+}
+
+TEST(JsonStdStringWriterTest, HelloWorld) {
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  writer->HandleMapBegin();
+  WriteUTF8AsUTF16(writer.get(), "msg1");
+  WriteUTF8AsUTF16(writer.get(), "Hello, 🌎.");
+  std::string key = "msg1-as-utf8";
+  std::string value = "Hello, 🌎.";
+  writer->HandleString8(SpanFromStdString(key));
+  writer->HandleString8(SpanFromStdString(value));
+  WriteUTF8AsUTF16(writer.get(), "msg2");
+  WriteUTF8AsUTF16(writer.get(), "\\\b\r\n\t\f\"");
+  WriteUTF8AsUTF16(writer.get(), "nested");
+  writer->HandleMapBegin();
+  WriteUTF8AsUTF16(writer.get(), "double");
+  writer->HandleDouble(3.1415);
+  WriteUTF8AsUTF16(writer.get(), "int");
+  writer->HandleInt32(-42);
+  WriteUTF8AsUTF16(writer.get(), "bool");
+  writer->HandleBool(false);
+  WriteUTF8AsUTF16(writer.get(), "null");
+  writer->HandleNull();
+  writer->HandleMapEnd();
+  WriteUTF8AsUTF16(writer.get(), "array");
+  writer->HandleArrayBegin();
+  writer->HandleInt32(1);
+  writer->HandleInt32(2);
+  writer->HandleInt32(3);
+  writer->HandleArrayEnd();
+  writer->HandleMapEnd();
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(
+      "{\"msg1\":\"Hello, \\ud83c\\udf0e.\","
+      "\"msg1-as-utf8\":\"Hello, \\ud83c\\udf0e.\","
+      "\"msg2\":\"\\\\\\b\\r\\n\\t\\f\\\"\","
+      "\"nested\":{\"double\":3.1415,\"int\":-42,"
+      "\"bool\":false,\"null\":null},\"array\":[1,2,3]}",
+      out);
+}
+
+TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
+  // The encoder emits binary submitted to StreamingParserHandler::HandleBinary
+  // as base64. The following three examples are taken from
+  // https://en.wikipedia.org/wiki/Base64.
+  {
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    writer->HandleBinary(SpanFromVector(std::vector<uint8_t>({'M', 'a', 'n'})));
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ("\"TWFu\"", out);
+  }
+  {
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    writer->HandleBinary(SpanFromVector(std::vector<uint8_t>({'M', 'a'})));
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ("\"TWE=\"", out);
+  }
+  {
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    writer->HandleBinary(SpanFromVector(std::vector<uint8_t>({'M'})));
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ("\"TQ==\"", out);
+  }
+  {  // "Hello, world.", verified with base64decode.org.
+    std::string out;
+    Status status;
+    std::unique_ptr<StreamingParserHandler> writer =
+        NewJSONEncoder(GetTestPlatform(), &out, &status);
+    writer->HandleBinary(SpanFromVector(std::vector<uint8_t>(
+        {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'})));
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ("\"SGVsbG8sIHdvcmxkLg==\"", out);
+  }
+}
+
+TEST(JsonStdStringWriterTest, HandlesErrors) {
+  // When an error is sent via HandleError, it saves it in the provided
+  // status and clears the output.
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> writer =
+      NewJSONEncoder(GetTestPlatform(), &out, &status);
+  writer->HandleMapBegin();
+  WriteUTF8AsUTF16(writer.get(), "msg1");
+  writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42});
+  EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error);
+  EXPECT_EQ(42, status.pos);
+  EXPECT_EQ("", out);
+}
+
+// We'd use Gmock but unfortunately it only handles copyable return types.
+class MockPlatform : public Platform {
+ public:
+  // Not implemented.
+  bool StrToD(const char* str, double* result) const override { return false; }
+
+  // A map with pre-registered responses for DToSTr.
+  std::map<double, std::string> dtostr_responses;
+
+  std::unique_ptr<char[]> DToStr(double value) const override {
+    auto it = dtostr_responses.find(value);
+    CHECK(it != dtostr_responses.end());
+    const std::string& str = it->second;
+    std::unique_ptr<char[]> response(new char[str.size() + 1]);
+    memcpy(response.get(), str.c_str(), str.size() + 1);
+    return response;
+  }
+};
+
+TEST(JsonStdStringWriterTest, DoubleToString) {
+  // This "broken" platform responds without the leading 0 before the
+  // decimal dot, so it'd be invalid JSON.
+  MockPlatform platform;
+  platform.dtostr_responses[.1] = ".1";
+  platform.dtostr_responses[-.7] = "-.7";
+
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> writer =
+      NewJSONEncoder(&platform, &out, &status);
+  writer->HandleArrayBegin();
+  writer->HandleDouble(.1);
+  writer->HandleDouble(-.7);
+  writer->HandleArrayEnd();
+  EXPECT_EQ("[0.1,-0.7]", out);
+}
+
+// =============================================================================
+// json::ParseJSON - for receiving streaming parser events for JSON
+// =============================================================================
+
+class Log : public StreamingParserHandler {
+ public:
+  void HandleMapBegin() override { log_ << "map begin\n"; }
+
+  void HandleMapEnd() override { log_ << "map end\n"; }
+
+  void HandleArrayBegin() override { log_ << "array begin\n"; }
+
+  void HandleArrayEnd() override { log_ << "array end\n"; }
+
+  void HandleString8(span<uint8_t> chars) override {
+    log_ << "string8: " << std::string(chars.begin(), chars.end()) << "\n";
+  }
+
+  void HandleString16(span<uint16_t> chars) override {
+    log_ << "string16: " << UTF16ToUTF8(chars) << "\n";
+  }
+
+  void HandleBinary(span<uint8_t> bytes) override {
+    // JSON doesn't have native support for arbitrary bytes, so our parser will
+    // never call this.
+    CHECK(false);
+  }
+
+  void HandleDouble(double value) override {
+    log_ << "double: " << value << "\n";
+  }
+
+  void HandleInt32(int32_t value) override { log_ << "int: " << value << "\n"; }
+
+  void HandleBool(bool value) override { log_ << "bool: " << value << "\n"; }
+
+  void HandleNull() override { log_ << "null\n"; }
+
+  void HandleError(Status status) override { status_ = status; }
+
+  std::string str() const { return status_.ok() ? log_.str() : ""; }
+
+  Status status() const { return status_; }
+
+ private:
+  std::ostringstream log_;
+  Status status_;
+};
+
+class JsonParserTest : public ::testing::Test {
+ protected:
+  Log log_;
+};
+
+TEST_F(JsonParserTest, SimpleDictionary) {
+  std::string json = "{\"foo\": 42}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: foo\n"
+      "int: 42\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, Whitespace) {
+  std::string json = "\n  {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: msg\n"
+      "string16: Hello, world.\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, NestedDictionary) {
+  std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: foo\n"
+      "map begin\n"
+      "string16: bar\n"
+      "map begin\n"
+      "string16: baz\n"
+      "int: 1\n"
+      "map end\n"
+      "string16: bar2\n"
+      "int: 2\n"
+      "map end\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, Doubles) {
+  std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: foo\n"
+      "double: 3.1415\n"
+      "string16: bar\n"
+      "double: 3.1415\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, Unicode) {
+  // Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16.
+  std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: msg\n"
+      "string16: Hello, 🌎.\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, Unicode_ParseUtf16) {
+  // Globe character. utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E.
+  // Crescent moon character. utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19.
+
+  // We provide the moon with json escape, but the earth as utf16 input.
+  // Either way they arrive as utf8 (after decoding in log_.str()).
+  std::vector<uint16_t> json =
+      UTF8ToUTF16(SpanFromStdString("{\"space\": \"🌎 \\uD83C\\uDF19.\"}"));
+  ParseJSON(GetTestPlatform(), SpanFromVector(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: space\n"
+      "string16: 🌎 🌙.\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, Unicode_ParseUtf8) {
+  // Used below:
+  // гласность - example for 2 byte utf8, Russian word "glasnost"
+  // 屋 - example for 3 byte utf8, Chinese word for "house"
+  // 🌎 - example for 4 byte utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E.
+  // 🌙 - example for escapes: utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19.
+
+  // We provide the moon with json escape, but the earth as utf8 input.
+  // Either way they arrive as utf8 (after decoding in log_.str()).
+  std::string json =
+      "{"
+      "\"escapes\": \"\\uD83C\\uDF19\","
+      "\"2 byte\":\"гласность\","
+      "\"3 byte\":\"屋\","
+      "\"4 byte\":\"🌎\""
+      "}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: escapes\n"
+      "string16: 🌙\n"
+      "string16: 2 byte\n"
+      "string16: гласность\n"
+      "string16: 3 byte\n"
+      "string16: 屋\n"
+      "string16: 4 byte\n"
+      "string16: 🌎\n"
+      "map end\n",
+      log_.str());
+}
+
+TEST_F(JsonParserTest, UnprocessedInputRemainsError) {
+  // Trailing junk after the valid JSON.
+  std::string json = "{\"foo\": 3.1415} junk";
+  int64_t junk_idx = json.find("junk");
+  EXPECT_GT(junk_idx, 0);
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error);
+  EXPECT_EQ(junk_idx, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+std::string MakeNestedJson(int depth) {
+  std::string json;
+  for (int ii = 0; ii < depth; ++ii)
+    json += "{\"foo\":";
+  json += "42";
+  for (int ii = 0; ii < depth; ++ii)
+    json += "}";
+  return json;
+}
+
+TEST_F(JsonParserTest, StackLimitExceededError) {
+  // kStackLimit is 1000 (see json_parser.cc). First let's
+  // try with a small nested example.
+  std::string json_3 = MakeNestedJson(3);
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json_3), &log_);
+  EXPECT_TRUE(log_.status().ok());
+  EXPECT_EQ(
+      "map begin\n"
+      "string16: foo\n"
+      "map begin\n"
+      "string16: foo\n"
+      "map begin\n"
+      "string16: foo\n"
+      "int: 42\n"
+      "map end\n"
+      "map end\n"
+      "map end\n",
+      log_.str());
+
+  // Now with kStackLimit (1000).
+  log_ = Log();
+  std::string json_limit = MakeNestedJson(1000);
+  ParseJSON(GetTestPlatform(),
+            span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
+                          json_limit.size()),
+            &log_);
+  EXPECT_TRUE(log_.status().ok());
+  // Now with kStackLimit + 1 (1001) - it exceeds in the innermost instance.
+  log_ = Log();
+  std::string exceeded = MakeNestedJson(1001);
+  ParseJSON(GetTestPlatform(), SpanFromStdString(exceeded), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
+  EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 1001),
+            log_.status().pos);
+  // Now way past the limit. Still, the point of exceeding is 1001.
+  log_ = Log();
+  std::string far_out = MakeNestedJson(10000);
+  ParseJSON(GetTestPlatform(), SpanFromStdString(far_out), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
+  EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 1001),
+            log_.status().pos);
+}
+
+TEST_F(JsonParserTest, NoInputError) {
+  std::string json = "";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error);
+  EXPECT_EQ(0, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, InvalidTokenError) {
+  std::string json = "|";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error);
+  EXPECT_EQ(0, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, InvalidNumberError) {
+  // Mantissa exceeds max (the constant used here is int64_t max).
+  std::string json = "1E9223372036854775807";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error);
+  EXPECT_EQ(0, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, InvalidStringError) {
+  // \x22 is an unsupported escape sequence
+  std::string json = "\"foo\\x22\"";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error);
+  EXPECT_EQ(0, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, UnexpectedArrayEndError) {
+  std::string json = "[1,2,]";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error);
+  EXPECT_EQ(5, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
+  std::string json = "[1,2 2";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
+            log_.status().error);
+  EXPECT_EQ(5, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, StringLiteralExpectedError) {
+  // There's an error because the key bar, a string, is not terminated.
+  std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error);
+  EXPECT_EQ(16, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, ColonExpectedError) {
+  std::string json = "{\"foo\", 42}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error);
+  EXPECT_EQ(6, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, UnexpectedMapEndError) {
+  std::string json = "{\"foo\": 42, }";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_MAP_END, log_.status().error);
+  EXPECT_EQ(12, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
+  // The second separator should be a comma.
+  std::string json = "{\"foo\": 3.1415: \"bar\": 0}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, log_.status().error);
+  EXPECT_EQ(14, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+
+TEST_F(JsonParserTest, ValueExpectedError) {
+  std::string json = "}";
+  ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_);
+  EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error);
+  EXPECT_EQ(0, log_.status().pos);
+  EXPECT_EQ("", log_.str());
+}
+}  // namespace json
+}  // namespace inspector_protocol_encoding
diff --git a/third_party/inspector_protocol/encoding/json_parser.cc b/third_party/inspector_protocol/encoding/json_parser.cc
deleted file mode 100644
index 27a1f23..0000000
--- a/third_party/inspector_protocol/encoding/json_parser.cc
+++ /dev/null
@@ -1,588 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "json_parser.h"
-
-#include <cassert>
-#include <limits>
-#include <string>
-#include "status.h"
-
-namespace inspector_protocol {
-namespace {
-const int kStackLimit = 1000;
-
-enum Token {
-  ObjectBegin,
-  ObjectEnd,
-  ArrayBegin,
-  ArrayEnd,
-  StringLiteral,
-  Number,
-  BoolTrue,
-  BoolFalse,
-  NullToken,
-  ListSeparator,
-  ObjectPairSeparator,
-  InvalidToken,
-  NoInput
-};
-
-const char* const kNullString = "null";
-const char* const kTrueString = "true";
-const char* const kFalseString = "false";
-
-template <typename Char>
-class JsonParser {
- public:
-  JsonParser(const Platform* platform, JSONParserHandler* handler)
-      : platform_(platform), handler_(handler) {}
-
-  void Parse(const Char* start, std::size_t length) {
-    start_pos_ = start;
-    const Char* end = start + length;
-    const Char* tokenEnd;
-    ParseValue(start, end, &tokenEnd, 0);
-    if (tokenEnd != end) {
-      HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd);
-    }
-  }
-
- private:
-  bool CharsToDouble(const uint16_t* chars,
-                     std::size_t length,
-                     double* result) {
-    std::string buffer;
-    buffer.reserve(length + 1);
-    for (std::size_t ii = 0; ii < length; ++ii) {
-      bool is_ascii = !(chars[ii] & ~0x7F);
-      if (!is_ascii) return false;
-      buffer.push_back(static_cast<char>(chars[ii]));
-    }
-    return platform_->StrToD(buffer.c_str(), result);
-  }
-
-  bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) {
-    std::string buffer(reinterpret_cast<const char*>(chars), length);
-    return platform_->StrToD(buffer.c_str(), result);
-  }
-
-  static bool ParseConstToken(const Char* start, const Char* end,
-                              const Char** token_end, const char* token) {
-    // |token| is \0 terminated, it's one of the constants at top of the file.
-    while (start < end && *token != '\0' && *start++ == *token++) {
-    }
-    if (*token != '\0') return false;
-    *token_end = start;
-    return true;
-  }
-
-  static bool ReadInt(const Char* start, const Char* end,
-                      const Char** token_end, bool allow_leading_zeros) {
-    if (start == end) return false;
-    bool has_leading_zero = '0' == *start;
-    int length = 0;
-    while (start < end && '0' <= *start && *start <= '9') {
-      ++start;
-      ++length;
-    }
-    if (!length) return false;
-    if (!allow_leading_zeros && length > 1 && has_leading_zero) return false;
-    *token_end = start;
-    return true;
-  }
-
-  static bool ParseNumberToken(const Char* start, const Char* end,
-                               const Char** token_end) {
-    // We just grab the number here. We validate the size in DecodeNumber.
-    // According to RFC4627, a valid number is: [minus] int [frac] [exp]
-    if (start == end) return false;
-    Char c = *start;
-    if ('-' == c) ++start;
-
-    if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false))
-      return false;
-    if (start == end) {
-      *token_end = start;
-      return true;
-    }
-
-    // Optional fraction part
-    c = *start;
-    if ('.' == c) {
-      ++start;
-      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
-        return false;
-      if (start == end) {
-        *token_end = start;
-        return true;
-      }
-      c = *start;
-    }
-
-    // Optional exponent part
-    if ('e' == c || 'E' == c) {
-      ++start;
-      if (start == end) return false;
-      c = *start;
-      if ('-' == c || '+' == c) {
-        ++start;
-        if (start == end) return false;
-      }
-      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
-        return false;
-    }
-
-    *token_end = start;
-    return true;
-  }
-
-  static bool ReadHexDigits(const Char* start, const Char* end,
-                            const Char** token_end, int digits) {
-    if (end - start < digits) return false;
-    for (int i = 0; i < digits; ++i) {
-      Char c = *start++;
-      if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
-            ('A' <= c && c <= 'F')))
-        return false;
-    }
-    *token_end = start;
-    return true;
-  }
-
-  static bool ParseStringToken(const Char* start, const Char* end,
-                               const Char** token_end) {
-    while (start < end) {
-      Char c = *start++;
-      if ('\\' == c) {
-        if (start == end) return false;
-        c = *start++;
-        // Make sure the escaped char is valid.
-        switch (c) {
-          case 'x':
-            if (!ReadHexDigits(start, end, &start, 2)) return false;
-            break;
-          case 'u':
-            if (!ReadHexDigits(start, end, &start, 4)) return false;
-            break;
-          case '\\':
-          case '/':
-          case 'b':
-          case 'f':
-          case 'n':
-          case 'r':
-          case 't':
-          case 'v':
-          case '"':
-            break;
-          default:
-            return false;
-        }
-      } else if ('"' == c) {
-        *token_end = start;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  static bool SkipComment(const Char* start, const Char* end,
-                          const Char** comment_end) {
-    if (start == end) return false;
-
-    if (*start != '/' || start + 1 >= end) return false;
-    ++start;
-
-    if (*start == '/') {
-      // Single line comment, read to newline.
-      for (++start; start < end; ++start) {
-        if (*start == '\n' || *start == '\r') {
-          *comment_end = start + 1;
-          return true;
-        }
-      }
-      *comment_end = end;
-      // Comment reaches end-of-input, which is fine.
-      return true;
-    }
-
-    if (*start == '*') {
-      Char previous = '\0';
-      // Block comment, read until end marker.
-      for (++start; start < end; previous = *start++) {
-        if (previous == '*' && *start == '/') {
-          *comment_end = start + 1;
-          return true;
-        }
-      }
-      // Block comment must close before end-of-input.
-      return false;
-    }
-
-    return false;
-  }
-
-  static bool IsSpaceOrNewLine(Char c) {
-    // \v = vertial tab; \f = form feed page break.
-    return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' ||
-           c == '\t';
-  }
-
-  static void SkipWhitespaceAndComments(const Char* start, const Char* end,
-                                        const Char** whitespace_end) {
-    while (start < end) {
-      if (IsSpaceOrNewLine(*start)) {
-        ++start;
-      } else if (*start == '/') {
-        const Char* comment_end;
-        if (!SkipComment(start, end, &comment_end)) break;
-        start = comment_end;
-      } else {
-        break;
-      }
-    }
-    *whitespace_end = start;
-  }
-
-  static Token ParseToken(const Char* start, const Char* end,
-                          const Char** tokenStart, const Char** token_end) {
-    SkipWhitespaceAndComments(start, end, tokenStart);
-    start = *tokenStart;
-
-    if (start == end) return NoInput;
-
-    switch (*start) {
-      case 'n':
-        if (ParseConstToken(start, end, token_end, kNullString))
-          return NullToken;
-        break;
-      case 't':
-        if (ParseConstToken(start, end, token_end, kTrueString))
-          return BoolTrue;
-        break;
-      case 'f':
-        if (ParseConstToken(start, end, token_end, kFalseString))
-          return BoolFalse;
-        break;
-      case '[':
-        *token_end = start + 1;
-        return ArrayBegin;
-      case ']':
-        *token_end = start + 1;
-        return ArrayEnd;
-      case ',':
-        *token_end = start + 1;
-        return ListSeparator;
-      case '{':
-        *token_end = start + 1;
-        return ObjectBegin;
-      case '}':
-        *token_end = start + 1;
-        return ObjectEnd;
-      case ':':
-        *token_end = start + 1;
-        return ObjectPairSeparator;
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-      case '-':
-        if (ParseNumberToken(start, end, token_end)) return Number;
-        break;
-      case '"':
-        if (ParseStringToken(start + 1, end, token_end)) return StringLiteral;
-        break;
-    }
-    return InvalidToken;
-  }
-
-  static int HexToInt(Char c) {
-    if ('0' <= c && c <= '9') return c - '0';
-    if ('A' <= c && c <= 'F') return c - 'A' + 10;
-    if ('a' <= c && c <= 'f') return c - 'a' + 10;
-    assert(false);  // Unreachable.
-    return 0;
-  }
-
-  static bool DecodeString(const Char* start, const Char* end,
-                           std::vector<uint16_t>* output) {
-    if (start == end) return true;
-    if (start > end) return false;
-    output->reserve(end - start);
-    while (start < end) {
-      uint16_t c = *start++;
-      // If the |Char| we're dealing with is really a byte, then
-      // we have utf8 here, and we need to check for multibyte characters
-      // and transcode them to utf16 (either one or two utf16 chars).
-      if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) {
-        // Inspect the leading byte to figure out how long the utf8
-        // byte sequence is; while doing this initialize |codepoint|
-        // with the first few bits.
-        // See table in: https://en.wikipedia.org/wiki/UTF-8
-        // byte one is 110x xxxx -> 2 byte utf8 sequence
-        // byte one is 1110 xxxx -> 3 byte utf8 sequence
-        // byte one is 1111 0xxx -> 4 byte utf8 sequence
-        uint32_t codepoint;
-        int num_bytes_left;
-        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
-          num_bytes_left = 1;
-          codepoint = c & 0x1f;
-        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
-          num_bytes_left = 2;
-          codepoint = c & 0x0f;
-        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
-          codepoint = c & 0x07;
-          num_bytes_left = 3;
-        } else {
-          return false;  // invalid leading byte
-        }
-
-        // If we have enough bytes in our inpput, decode the remaining ones
-        // belonging to this Unicode character into |codepoint|.
-        if (start + num_bytes_left > end) return false;
-        while (num_bytes_left > 0) {
-          c = *start++;
-          --num_bytes_left;
-          // Check the next byte is a continuation byte, that is 10xx xxxx.
-          if ((c & 0xc0) != 0x80) return false;
-          codepoint = (codepoint << 6) | (c & 0x3f);
-        }
-
-        // Disallow overlong encodings for ascii characters, as these
-        // would include " and other characters significant to JSON
-        // string termination / control.
-        if (codepoint < 0x7f) return false;
-        // Invalid in UTF8, and can't be represented in UTF16 anyway.
-        if (codepoint > 0x10ffff) return false;
-
-        // So, now we transcode to UTF16,
-        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
-        // for either one or two 16 bit characters.
-        if (codepoint < 0xffff) {
-          output->push_back(codepoint);
-          continue;
-        }
-        codepoint -= 0x10000;
-        output->push_back((codepoint >> 10) + 0xd800);    // high surrogate
-        output->push_back((codepoint & 0x3ff) + 0xdc00);  // low surrogate
-        continue;
-      }
-      if ('\\' != c) {
-        output->push_back(c);
-        continue;
-      }
-      if (start == end) return false;
-      c = *start++;
-
-      if (c == 'x') {
-        // \x is not supported.
-        return false;
-      }
-
-      switch (c) {
-        case '"':
-        case '/':
-        case '\\':
-          break;
-        case 'b':
-          c = '\b';
-          break;
-        case 'f':
-          c = '\f';
-          break;
-        case 'n':
-          c = '\n';
-          break;
-        case 'r':
-          c = '\r';
-          break;
-        case 't':
-          c = '\t';
-          break;
-        case 'v':
-          c = '\v';
-          break;
-        case 'u':
-          c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) +
-              (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3));
-          start += 4;
-          break;
-        default:
-          return false;
-      }
-      output->push_back(c);
-    }
-    return true;
-  }
-
-  void ParseValue(const Char* start, const Char* end,
-                  const Char** value_token_end, int depth) {
-    if (depth > kStackLimit) {
-      HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start);
-      return;
-    }
-    const Char* token_start;
-    const Char* token_end;
-    Token token = ParseToken(start, end, &token_start, &token_end);
-    switch (token) {
-      case NoInput:
-        HandleError(Error::JSON_PARSER_NO_INPUT, token_start);
-        return;
-      case InvalidToken:
-        HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start);
-        return;
-      case NullToken:
-        handler_->HandleNull();
-        break;
-      case BoolTrue:
-        handler_->HandleBool(true);
-        break;
-      case BoolFalse:
-        handler_->HandleBool(false);
-        break;
-      case Number: {
-        double value;
-        if (!CharsToDouble(token_start, token_end - token_start, &value)) {
-          HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start);
-          return;
-        }
-        if (value >= std::numeric_limits<int32_t>::min() &&
-            value <= std::numeric_limits<int32_t>::max() &&
-            static_cast<int32_t>(value) == value)
-          handler_->HandleInt32(static_cast<int32_t>(value));
-        else
-          handler_->HandleDouble(value);
-        break;
-      }
-      case StringLiteral: {
-        std::vector<uint16_t> value;
-        bool ok = DecodeString(token_start + 1, token_end - 1, &value);
-        if (!ok) {
-          HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
-          return;
-        }
-        handler_->HandleString16(span<uint16_t>(value.data(), value.size()));
-        break;
-      }
-      case ArrayBegin: {
-        handler_->HandleArrayBegin();
-        start = token_end;
-        token = ParseToken(start, end, &token_start, &token_end);
-        while (token != ArrayEnd) {
-          ParseValue(start, end, &token_end, depth + 1);
-          if (error_) return;
-
-          // After a list value, we expect a comma or the end of the list.
-          start = token_end;
-          token = ParseToken(start, end, &token_start, &token_end);
-          if (token == ListSeparator) {
-            start = token_end;
-            token = ParseToken(start, end, &token_start, &token_end);
-            if (token == ArrayEnd) {
-              HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start);
-              return;
-            }
-          } else if (token != ArrayEnd) {
-            // Unexpected value after list value. Bail out.
-            HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
-                        token_start);
-            return;
-          }
-        }
-        handler_->HandleArrayEnd();
-        break;
-      }
-      case ObjectBegin: {
-        handler_->HandleObjectBegin();
-        start = token_end;
-        token = ParseToken(start, end, &token_start, &token_end);
-        while (token != ObjectEnd) {
-          if (token != StringLiteral) {
-            HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED,
-                        token_start);
-            return;
-          }
-          std::vector<uint16_t> key;
-          if (!DecodeString(token_start + 1, token_end - 1, &key)) {
-            HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
-            return;
-          }
-          handler_->HandleString16(span<uint16_t>(key.data(), key.size()));
-          start = token_end;
-
-          token = ParseToken(start, end, &token_start, &token_end);
-          if (token != ObjectPairSeparator) {
-            HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start);
-            return;
-          }
-          start = token_end;
-
-          ParseValue(start, end, &token_end, depth + 1);
-          if (error_) return;
-          start = token_end;
-
-          // After a key/value pair, we expect a comma or the end of the
-          // object.
-          token = ParseToken(start, end, &token_start, &token_end);
-          if (token == ListSeparator) {
-            start = token_end;
-            token = ParseToken(start, end, &token_start, &token_end);
-            if (token == ObjectEnd) {
-              HandleError(Error::JSON_PARSER_UNEXPECTED_OBJECT_END,
-                          token_start);
-              return;
-            }
-          } else if (token != ObjectEnd) {
-            // Unexpected value after last object value. Bail out.
-            HandleError(Error::JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED,
-                        token_start);
-            return;
-          }
-        }
-        handler_->HandleObjectEnd();
-        break;
-      }
-
-      default:
-        // We got a token that's not a value.
-        HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start);
-        return;
-    }
-
-    SkipWhitespaceAndComments(token_end, end, value_token_end);
-  }
-
-  void HandleError(Error error, const Char* pos) {
-    assert(error != Error::OK);
-    if (!error_) {
-      handler_->HandleError(Status{error, pos - start_pos_});
-      error_ = true;
-    }
-  }
-
-  const Char* start_pos_ = nullptr;
-  bool error_ = false;
-  const Platform* platform_;
-  JSONParserHandler* handler_;
-};
-}  // namespace
-
-void ParseJSONChars(const Platform* platform, span<uint8_t> chars,
-                    JSONParserHandler* handler) {
-  JsonParser<uint8_t> parser(platform, handler);
-  parser.Parse(chars.data(), chars.size());
-}
-
-void ParseJSONChars(const Platform* platform, span<uint16_t> chars,
-                    JSONParserHandler* handler) {
-  JsonParser<uint16_t> parser(platform, handler);
-  parser.Parse(chars.data(), chars.size());
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/json_parser.h b/third_party/inspector_protocol/encoding/json_parser.h
deleted file mode 100644
index 55384be..0000000
--- a/third_party/inspector_protocol/encoding/json_parser.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_H_
-#define INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_H_
-
-#include <cstdint>
-#include <vector>
-#include "json_parser_handler.h"
-#include "platform.h"
-#include "span.h"
-
-namespace inspector_protocol {
-// JSON parsing routines.
-void ParseJSONChars(const Platform* platform, span<uint8_t> chars,
-                    JSONParserHandler* handler);
-void ParseJSONChars(const Platform* platform, span<uint16_t> chars,
-                    JSONParserHandler* handler);
-}  // namespace inspector_protocol
-
-#endif  // INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_H_
diff --git a/third_party/inspector_protocol/encoding/json_parser_handler.h b/third_party/inspector_protocol/encoding/json_parser_handler.h
deleted file mode 100644
index d90b65f7..0000000
--- a/third_party/inspector_protocol/encoding/json_parser_handler.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_HANDLER_H_
-#define INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_HANDLER_H_
-
-#include <cstdint>
-#include <vector>
-#include "span.h"
-#include "status.h"
-
-namespace inspector_protocol {
-// Handler interface for JSON parser events. See also json_parser.h.
-class JSONParserHandler {
- public:
-  virtual ~JSONParserHandler() = default;
-  virtual void HandleObjectBegin() = 0;
-  virtual void HandleObjectEnd() = 0;
-  virtual void HandleArrayBegin() = 0;
-  virtual void HandleArrayEnd() = 0;
-  virtual void HandleString8(span<uint8_t> chars) = 0;
-  virtual void HandleString16(span<uint16_t> chars) = 0;
-  virtual void HandleBinary(std::vector<uint8_t> bytes) = 0;
-  virtual void HandleDouble(double value) = 0;
-  virtual void HandleInt32(int32_t value) = 0;
-  virtual void HandleBool(bool value) = 0;
-  virtual void HandleNull() = 0;
-
-  // The parser may send one error even after other events have already
-  // been received. Client code is reponsible to then discard the
-  // already processed events.
-  // |error| must be an eror, as in, |error.is_ok()| can't be true.
-  virtual void HandleError(Status error) = 0;
-};
-}  // namespace inspector_protocol
-
-#endif  // INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_HANDLER_H_
diff --git a/third_party/inspector_protocol/encoding/json_parser_test.cc b/third_party/inspector_protocol/encoding/json_parser_test.cc
deleted file mode 100644
index 2e63129..0000000
--- a/third_party/inspector_protocol/encoding/json_parser_test.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "json_parser.h"
-
-#include <iostream>
-#include <sstream>
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "gtest/gtest.h"
-#include "linux_dev_platform.h"
-
-namespace inspector_protocol {
-class Log : public JSONParserHandler {
- public:
-  void HandleObjectBegin() override { log_ << "object begin\n"; }
-
-  void HandleObjectEnd() override { log_ << "object end\n"; }
-
-  void HandleArrayBegin() override { log_ << "array begin\n"; }
-
-  void HandleArrayEnd() override { log_ << "array end\n"; }
-
-  void HandleString8(span<uint8_t> chars) override {
-    base::StringPiece foo(reinterpret_cast<const char*>(chars.data()),
-                          chars.size());
-    log_ << "string8: " << foo << "\n";
-  }
-
-  void HandleString16(span<uint16_t> chars) override {
-    base::StringPiece16 foo(reinterpret_cast<const base::char16*>(chars.data()),
-                            chars.size());
-    log_ << "string16: " << base::UTF16ToUTF8(foo) << "\n";
-  }
-
-  void HandleBinary(std::vector<uint8_t> bytes) override {
-    // JSON doesn't have native support for arbitrary bytes, so our parser will
-    // never call this.
-    assert(false);
-  }
-
-  void HandleDouble(double value) override {
-    log_ << "double: " << value << "\n";
-  }
-
-  void HandleInt32(int32_t value) override { log_ << "int: " << value << "\n"; }
-
-  void HandleBool(bool value) override { log_ << "bool: " << value << "\n"; }
-
-  void HandleNull() override { log_ << "null\n"; }
-
-  void HandleError(Status status) override { status_ = status; }
-
-  std::string str() const { return status_.ok() ? log_.str() : ""; }
-
-  Status status() const { return status_; }
-
- private:
-  std::ostringstream log_;
-  Status status_;
-};
-
-class JsonParserTest : public ::testing::Test {
- protected:
-  Log log_;
-};
-
-TEST_F(JsonParserTest, SimpleDictionary) {
-  std::string json = "{\"foo\": 42}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: foo\n"
-      "int: 42\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, Whitespace) {
-  std::string json = "\n  {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: msg\n"
-      "string16: Hello, world.\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, NestedDictionary) {
-  std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: foo\n"
-      "object begin\n"
-      "string16: bar\n"
-      "object begin\n"
-      "string16: baz\n"
-      "int: 1\n"
-      "object end\n"
-      "string16: bar2\n"
-      "int: 2\n"
-      "object end\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, Doubles) {
-  std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: foo\n"
-      "double: 3.1415\n"
-      "string16: bar\n"
-      "double: 3.1415\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, Unicode) {
-  // Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16.
-  std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: msg\n"
-      "string16: Hello, 🌎.\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, Unicode_ParseUtf16) {
-  // Globe character. utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E.
-  // Crescent moon character. utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19.
-
-  // We provide the moon with json escape, but the earth as utf16 input.
-  // Either way they arrive as utf8 (after decoding in log_.str()).
-  base::string16 json = base::UTF8ToUTF16("{\"space\": \"🌎 \\uD83C\\uDF19.\"}");
-  ParseJSONChars(GetLinuxDevPlatform(),
-                 span<uint16_t>(reinterpret_cast<const uint16_t*>(json.data()),
-                                json.size()),
-                 &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: space\n"
-      "string16: 🌎 🌙.\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, Unicode_ParseUtf8) {
-  // Used below:
-  // гласность - example for 2 byte utf8, Russian word "glasnost"
-  // 屋 - example for 3 byte utf8, Chinese word for "house"
-  // 🌎 - example for 4 byte utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E.
-  // 🌙 - example for escapes: utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19.
-
-  // We provide the moon with json escape, but the earth as utf8 input.
-  // Either way they arrive as utf8 (after decoding in log_.str()).
-  std::string json =
-      "{"
-      "\"escapes\": \"\\uD83C\\uDF19\","
-      "\"2 byte\":\"гласность\","
-      "\"3 byte\":\"屋\","
-      "\"4 byte\":\"🌎\""
-      "}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: escapes\n"
-      "string16: 🌙\n"
-      "string16: 2 byte\n"
-      "string16: гласность\n"
-      "string16: 3 byte\n"
-      "string16: 屋\n"
-      "string16: 4 byte\n"
-      "string16: 🌎\n"
-      "object end\n",
-      log_.str());
-}
-
-TEST_F(JsonParserTest, UnprocessedInputRemainsError) {
-  // Trailing junk after the valid JSON.
-  std::string json = "{\"foo\": 3.1415} junk";
-  int64_t junk_idx = json.find("junk");
-  EXPECT_GT(junk_idx, 0);
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error);
-  EXPECT_EQ(junk_idx, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-std::string MakeNestedJson(int depth) {
-  std::string json;
-  for (int ii = 0; ii < depth; ++ii) json += "{\"foo\":";
-  json += "42";
-  for (int ii = 0; ii < depth; ++ii) json += "}";
-  return json;
-}
-
-TEST_F(JsonParserTest, StackLimitExceededError) {
-  // kStackLimit is 1000 (see json_parser.cc). First let's
-  // try with a small nested example.
-  std::string json_3 = MakeNestedJson(3);
-  ParseJSONChars(GetLinuxDevPlatform(),
-                 span<uint8_t>(reinterpret_cast<const uint8_t*>(json_3.data()),
-                               json_3.size()),
-                 &log_);
-  EXPECT_TRUE(log_.status().ok());
-  EXPECT_EQ(
-      "object begin\n"
-      "string16: foo\n"
-      "object begin\n"
-      "string16: foo\n"
-      "object begin\n"
-      "string16: foo\n"
-      "int: 42\n"
-      "object end\n"
-      "object end\n"
-      "object end\n",
-      log_.str());
-
-  // Now with kStackLimit (1000).
-  log_ = Log();
-  std::string json_limit = MakeNestedJson(1000);
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
-                    json_limit.size()),
-      &log_);
-  EXPECT_TRUE(log_.status().ok());
-  // Now with kStackLimit + 1 (1001) - it exceeds in the innermost instance.
-  log_ = Log();
-  std::string exceeded = MakeNestedJson(1001);
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(exceeded.data()),
-                    exceeded.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
-  EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 1001),
-            log_.status().pos);
-  // Now way past the limit. Still, the point of exceeding is 1001.
-  log_ = Log();
-  std::string far_out = MakeNestedJson(10000);
-  ParseJSONChars(GetLinuxDevPlatform(),
-                 span<uint8_t>(reinterpret_cast<const uint8_t*>(far_out.data()),
-                               far_out.size()),
-                 &log_);
-  EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
-  EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 1001),
-            log_.status().pos);
-}
-
-TEST_F(JsonParserTest, NoInputError) {
-  std::string json = "";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error);
-  EXPECT_EQ(0, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, InvalidTokenError) {
-  std::string json = "|";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error);
-  EXPECT_EQ(0, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, InvalidNumberError) {
-  // Mantissa exceeds max (the constant used here is int64_t max).
-  std::string json = "1E9223372036854775807";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error);
-  EXPECT_EQ(0, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, InvalidStringError) {
-  // \x22 is an unsupported escape sequence
-  std::string json = "\"foo\\x22\"";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error);
-  EXPECT_EQ(0, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, UnexpectedArrayEndError) {
-  std::string json = "[1,2,]";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error);
-  EXPECT_EQ(5, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
-  std::string json = "[1,2 2";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
-            log_.status().error);
-  EXPECT_EQ(5, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, StringLiteralExpectedError) {
-  // There's an error because the key bar, a string, is not terminated.
-  std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error);
-  EXPECT_EQ(16, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, ColonExpectedError) {
-  std::string json = "{\"foo\", 42}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error);
-  EXPECT_EQ(6, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, UnexpectedObjectEndError) {
-  std::string json = "{\"foo\": 42, }";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_OBJECT_END, log_.status().error);
-  EXPECT_EQ(12, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, CommaOrObjectEndExpectedError) {
-  // The second separator should be a comma.
-  std::string json = "{\"foo\": 3.1415: \"bar\": 0}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED,
-            log_.status().error);
-  EXPECT_EQ(14, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-TEST_F(JsonParserTest, ValueExpectedError) {
-  std::string json = "}";
-  ParseJSONChars(
-      GetLinuxDevPlatform(),
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()),
-      &log_);
-  EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error);
-  EXPECT_EQ(0, log_.status().pos);
-  EXPECT_EQ("", log_.str());
-}
-
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer.cc b/third_party/inspector_protocol/encoding/json_std_string_writer.cc
deleted file mode 100644
index 1c849cc..0000000
--- a/third_party/inspector_protocol/encoding/json_std_string_writer.cc
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "json_std_string_writer.h"
-#include <cassert>
-#include <stack>
-
-namespace inspector_protocol {
-namespace {
-// Prints |value| to |out| with 4 hex digits, most significant chunk first.
-void PrintHex(uint16_t value, std::string* out) {
-  for (int ii = 3; ii >= 0; --ii) {
-    int four_bits = 0xf & (value >> (4 * ii));
-    out->append(1, four_bits + ((four_bits <= 9) ? '0' : ('a' - 10)));
-  }
-}
-
-// In the writer below, we maintain a stack of State instances.
-// It is just enough to emit the appropriate delimiters and brackets
-// in JSON.
-enum class Container {
-  // Used for the top-level, initial state.
-  NONE,
-  // Inside a JSON object.
-  OBJECT,
-  // Inside a JSON array.
-  ARRAY
-};
-class State {
- public:
-  explicit State(Container container) : container_(container) {}
-  void StartElement(std::string* out) {
-    assert(container_ != Container::NONE || size_ == 0);
-    if (size_ != 0) {
-      char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':';
-      out->append(1, delim);
-    }
-    ++size_;
-  }
-  Container container() const { return container_; }
-
- private:
-  Container container_ = Container::NONE;
-  int size_ = 0;
-};
-
-constexpr char kBase64Table[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "abcdefghijklmnopqrstuvwxyz0123456789+/";
-
-void Base64Encode(const std::vector<uint8_t>& in, std::string* out) {
-  // The following three cases are based on the tables in the example
-  // section in https://en.wikipedia.org/wiki/Base64. We process three
-  // input bytes at a time, emitting 4 output bytes at a time.
-  std::size_t ii = 0;
-
-  // While possible, process three input bytes.
-  for (; ii + 3 <= in.size(); ii += 3) {
-    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2];
-    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
-    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
-    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
-    out->push_back(kBase64Table[twentyfour_bits & 0x3f]);
-  }
-  if (ii + 2 <= in.size()) {  // Process two input bytes.
-    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8);
-    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
-    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
-    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
-    out->push_back('=');  // Emit padding.
-    return;
-  }
-  if (ii + 1 <= in.size()) {  // Process a single input byte.
-    uint32_t twentyfour_bits = (in[ii] << 16);
-    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
-    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
-    out->push_back('=');  // Emit padding.
-    out->push_back('=');  // Emit padding.
-  }
-}
-
-// Implements a handler for JSON parser events to emit a JSON string.
-class Writer : public JSONParserHandler {
- public:
-  Writer(Platform* platform, std::string* out, Status* status)
-      : platform_(platform), out_(out), status_(status) {
-    *status_ = Status();
-    state_.emplace(Container::NONE);
-  }
-
-  void HandleObjectBegin() override {
-    if (!status_->ok()) return;
-    assert(!state_.empty());
-    state_.top().StartElement(out_);
-    state_.emplace(Container::OBJECT);
-    out_->append("{");
-  }
-
-  void HandleObjectEnd() override {
-    if (!status_->ok()) return;
-    assert(state_.size() >= 2 && state_.top().container() == Container::OBJECT);
-    state_.pop();
-    out_->append("}");
-  }
-
-  void HandleArrayBegin() override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    state_.emplace(Container::ARRAY);
-    out_->append("[");
-  }
-
-  void HandleArrayEnd() override {
-    if (!status_->ok()) return;
-    assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY);
-    state_.pop();
-    out_->append("]");
-  }
-
-  void HandleString16(span<uint16_t> chars) override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    out_->append("\"");
-    for (const uint16_t ch : chars) {
-      if (ch == '"') {
-        out_->append("\\\"");
-      } else if (ch == '\\') {
-        out_->append("\\\\");
-      } else if (ch == '\b') {
-        out_->append("\\b");
-      } else if (ch == '\f') {
-        out_->append("\\f");
-      } else if (ch == '\n') {
-        out_->append("\\n");
-      } else if (ch == '\r') {
-        out_->append("\\r");
-      } else if (ch == '\t') {
-        out_->append("\\t");
-      } else if (ch >= 32 && ch <= 126) {
-        out_->append(1, ch);
-      } else {
-        out_->append("\\u");
-        PrintHex(ch, out_);
-      }
-    }
-    out_->append("\"");
-  }
-
-  void HandleString8(span<uint8_t> chars) override {
-    if (!status_->ok())
-      return;
-    state_.top().StartElement(out_);
-    out_->append("\"");
-    for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) {
-      uint8_t c = chars[ii];
-      if (c == '"') {
-        out_->append("\\\"");
-      } else if (c == '\\') {
-        out_->append("\\\\");
-      } else if (c == '\b') {
-        out_->append("\\b");
-      } else if (c == '\f') {
-        out_->append("\\f");
-      } else if (c == '\n') {
-        out_->append("\\n");
-      } else if (c == '\r') {
-        out_->append("\\r");
-      } else if (c == '\t') {
-        out_->append("\\t");
-      } else if (c >= 32 && c <= 126) {
-        out_->append(1, c);
-      } else if (c < 32) {
-        out_->append("\\u");
-        PrintHex(static_cast<uint16_t>(c), out_);
-      } else {
-        // Inspect the leading byte to figure out how long the utf8
-        // byte sequence is; while doing this initialize |codepoint|
-        // with the first few bits.
-        // See table in: https://en.wikipedia.org/wiki/UTF-8
-        // byte one is 110x xxxx -> 2 byte utf8 sequence
-        // byte one is 1110 xxxx -> 3 byte utf8 sequence
-        // byte one is 1111 0xxx -> 4 byte utf8 sequence
-        uint32_t codepoint;
-        int num_bytes_left;
-        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
-          num_bytes_left = 1;
-          codepoint = c & 0x1f;
-        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
-          num_bytes_left = 2;
-          codepoint = c & 0x0f;
-        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
-          codepoint = c & 0x07;
-          num_bytes_left = 3;
-        } else {
-          continue;  // invalid leading byte
-        }
-
-        // If we have enough bytes in our input, decode the remaining ones
-        // belonging to this Unicode character into |codepoint|.
-        if (ii + num_bytes_left > chars.size())
-          continue;
-        while (num_bytes_left > 0) {
-          c = chars[++ii];
-          --num_bytes_left;
-          // Check the next byte is a continuation byte, that is 10xx xxxx.
-          if ((c & 0xc0) != 0x80)
-            continue;
-          codepoint = (codepoint << 6) | (c & 0x3f);
-        }
-
-        // Disallow overlong encodings for ascii characters, as these
-        // would include " and other characters significant to JSON
-        // string termination / control.
-        if (codepoint < 0x7f)
-          continue;
-        // Invalid in UTF8, and can't be represented in UTF16 anyway.
-        if (codepoint > 0x10ffff)
-          continue;
-
-        // So, now we transcode to UTF16,
-        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
-        // for either one or two 16 bit characters.
-        if (codepoint < 0xffff) {
-          out_->append("\\u");
-          PrintHex(static_cast<uint16_t>(codepoint), out_);
-          continue;
-        }
-        codepoint -= 0x10000;
-        // high surrogate
-        out_->append("\\u");
-        PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_);
-        // low surrogate
-        out_->append("\\u");
-        PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_);
-      }
-    }
-    out_->append("\"");
-  }
-
-  void HandleBinary(std::vector<uint8_t> bytes) override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    out_->append("\"");
-    Base64Encode(bytes, out_);
-    out_->append("\"");
-  }
-
-  void HandleDouble(double value) override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    std::unique_ptr<char[]> str_value = platform_->DToStr(value);
-
-    // DToStr may fail to emit a 0 before the decimal dot. E.g. this is
-    // the case in base::NumberToString in Chromium (which is based on
-    // dmg_fp). So, much like
-    // https://cs.chromium.org/chromium/src/base/json/json_writer.cc
-    // we probe for this and emit the leading 0 anyway if necessary.
-    const char* chars = str_value.get();
-    if (chars[0] == '.') {
-      out_->append("0");
-    } else if (chars[0] == '-' && chars[1] == '.') {
-      out_->append("-0");
-      ++chars;
-    }
-    out_->append(chars);
-  }
-
-  void HandleInt32(int32_t value) override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    out_->append(std::to_string(value));
-  }
-
-  void HandleBool(bool value) override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    out_->append(value ? "true" : "false");
-  }
-
-  void HandleNull() override {
-    if (!status_->ok()) return;
-    state_.top().StartElement(out_);
-    out_->append("null");
-  }
-
-  void HandleError(Status error) override {
-    assert(!error.ok());
-    *status_ = error;
-    out_->clear();
-  }
-
- private:
-  Platform* platform_;
-  std::string* out_;
-  Status* status_;
-  std::stack<State> state_;
-};
-}  // namespace
-
-std::unique_ptr<JSONParserHandler> NewJSONWriter(Platform* platform,
-                                                 std::string* out,
-                                                 Status* status) {
-  return std::unique_ptr<Writer>(new Writer(platform, out, status));
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer.h b/third_party/inspector_protocol/encoding/json_std_string_writer.h
deleted file mode 100644
index b2c9b634..0000000
--- a/third_party/inspector_protocol/encoding/json_std_string_writer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_JSON_STD_STRING_WRITER_H_
-#define INSPECTOR_PROTOCOL_ENCODING_JSON_STD_STRING_WRITER_H_
-
-#include <memory>
-#include <string>
-#include "json_parser_handler.h"
-#include "platform.h"
-
-namespace inspector_protocol {
-// Returns a handler object which will write ascii characters to |out|.
-// |status->ok()| will be false iff the handler routine HandleError() is called.
-// In that case, we'll stop emitting output.
-// Except for calling the HandleError routine at any time, the client
-// code must call the Handle* methods in an order in which they'd occur
-// in valid JSON; otherwise we may crash (the code uses assert).
-std::unique_ptr<JSONParserHandler> NewJSONWriter(Platform* platform,
-                                                 std::string* out,
-                                                 Status* status);
-}  // namespace inspector_protocol
-
-#endif  // INSPECTOR_PROTOCOL_ENCODING_JSON_STD_STRING_WRITER_H_
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc b/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc
deleted file mode 100644
index 553f8b2..0000000
--- a/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "json_std_string_writer.h"
-
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "gtest/gtest.h"
-#include "linux_dev_platform.h"
-
-namespace inspector_protocol {
-std::vector<uint16_t> UTF16String(const std::string& utf8) {
-  base::string16 string16 = base::UTF8ToUTF16(utf8);
-  return std::vector<uint16_t>(string16.data(),
-                               string16.data() + string16.size());
-}
-
-void WriteUTF8AsUTF16(JSONParserHandler* writer, const std::string& utf8) {
-  std::vector<uint16_t> utf16 = UTF16String(utf8);
-  writer->HandleString16(span<uint16_t>(utf16.data(), utf16.size()));
-}
-
-TEST(JsonStdStringWriterTest, HelloWorld) {
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  writer->HandleObjectBegin();
-  WriteUTF8AsUTF16(writer.get(), "msg1");
-  WriteUTF8AsUTF16(writer.get(), "Hello, 🌎.");
-  std::string key = "msg1-as-utf8";
-  std::string value = "Hello, 🌎.";
-  writer->HandleString8(
-      span<uint8_t>(reinterpret_cast<const uint8_t*>(key.data()), key.size()));
-  writer->HandleString8(span<uint8_t>(
-      reinterpret_cast<const uint8_t*>(value.data()), value.size()));
-  WriteUTF8AsUTF16(writer.get(), "msg2");
-  WriteUTF8AsUTF16(writer.get(), "\\\b\r\n\t\f\"");
-  WriteUTF8AsUTF16(writer.get(), "nested");
-  writer->HandleObjectBegin();
-  WriteUTF8AsUTF16(writer.get(), "double");
-  writer->HandleDouble(3.1415);
-  WriteUTF8AsUTF16(writer.get(), "int");
-  writer->HandleInt32(-42);
-  WriteUTF8AsUTF16(writer.get(), "bool");
-  writer->HandleBool(false);
-  WriteUTF8AsUTF16(writer.get(), "null");
-  writer->HandleNull();
-  writer->HandleObjectEnd();
-  WriteUTF8AsUTF16(writer.get(), "array");
-  writer->HandleArrayBegin();
-  writer->HandleInt32(1);
-  writer->HandleInt32(2);
-  writer->HandleInt32(3);
-  writer->HandleArrayEnd();
-  writer->HandleObjectEnd();
-  EXPECT_TRUE(status.ok());
-  EXPECT_EQ(
-      "{\"msg1\":\"Hello, \\ud83c\\udf0e.\","
-      "\"msg1-as-utf8\":\"Hello, \\ud83c\\udf0e.\","
-      "\"msg2\":\"\\\\\\b\\r\\n\\t\\f\\\"\","
-      "\"nested\":{\"double\":3.1415,\"int\":-42,"
-      "\"bool\":false,\"null\":null},\"array\":[1,2,3]}",
-      out);
-}
-
-TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
-  // The encoder emits binary submitted to JSONParserHandler::HandleBinary
-  // as base64. The following three examples are taken from
-  // https://en.wikipedia.org/wiki/Base64.
-  {
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    writer->HandleBinary({'M', 'a', 'n'});
-    EXPECT_TRUE(status.ok());
-    EXPECT_EQ("\"TWFu\"", out);
-  }
-  {
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    writer->HandleBinary({'M', 'a'});
-    EXPECT_TRUE(status.ok());
-    EXPECT_EQ("\"TWE=\"", out);
-  }
-  {
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    writer->HandleBinary({'M'});
-    EXPECT_TRUE(status.ok());
-    EXPECT_EQ("\"TQ==\"", out);
-  }
-  {  // "Hello, world.", verified with base64decode.org.
-    std::string out;
-    Status status;
-    std::unique_ptr<JSONParserHandler> writer =
-        NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-    writer->HandleBinary(
-        {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'});
-    EXPECT_TRUE(status.ok());
-    EXPECT_EQ("\"SGVsbG8sIHdvcmxkLg==\"", out);
-  }
-}
-
-TEST(JsonStdStringWriterTest, HandlesErrors) {
-  // When an error is sent via HandleError, it saves it in the provided
-  // status and clears the output.
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> writer =
-      NewJSONWriter(GetLinuxDevPlatform(), &out, &status);
-  writer->HandleObjectBegin();
-  WriteUTF8AsUTF16(writer.get(), "msg1");
-  writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42});
-  EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error);
-  EXPECT_EQ(42, status.pos);
-  EXPECT_EQ("", out);
-}
-
-// We'd use Gmock but unfortunately it only handles copyable return types.
-class MockPlatform : public Platform {
- public:
-  // Not implemented.
-  bool StrToD(const char* str, double* result) const override { return false; }
-
-  // A map with pre-registered responses for DToSTr.
-  std::map<double, std::string> dtostr_responses;
-
-  std::unique_ptr<char[]> DToStr(double value) const override {
-    auto it = dtostr_responses.find(value);
-    assert(it != dtostr_responses.end());
-    const std::string& str = it->second;
-    std::unique_ptr<char[]> response(new char[str.size() + 1]);
-    memcpy(response.get(), str.c_str(), str.size() + 1);
-    return response;
-  }
-};
-
-TEST(JsonStdStringWriterTest, DoubleToString) {
-  // This "broken" platform responds without the leading 0 before the
-  // decimal dot, so it'd be invalid JSON.
-  MockPlatform platform;
-  platform.dtostr_responses[.1] = ".1";
-  platform.dtostr_responses[-.7] = "-.7";
-
-  std::string out;
-  Status status;
-  std::unique_ptr<JSONParserHandler> writer =
-      NewJSONWriter(&platform, &out, &status);
-  writer->HandleArrayBegin();
-  writer->HandleDouble(.1);
-  writer->HandleDouble(-.7);
-  writer->HandleArrayEnd();
-  EXPECT_EQ("[0.1,-0.7]", out);
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/linux_dev_platform.cc b/third_party/inspector_protocol/encoding/linux_dev_platform.cc
deleted file mode 100644
index 142ca086..0000000
--- a/third_party/inspector_protocol/encoding/linux_dev_platform.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "linux_dev_platform.h"
-
-#include <clocale>
-#include <cstdlib>
-#include <cstring>
-#include <iomanip>
-#include <sstream>
-
-namespace inspector_protocol {
-namespace {
-class LinuxDevPlatform : public Platform {
-  bool StrToD(const char* str, double* result) const override {
-    // This is not thread-safe
-    // (see https://en.cppreference.com/w/cpp/locale/setlocale)
-    // but good enough for a unittest.
-    const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr);
-    char* end;
-    *result = std::strtod(str, &end);
-    std::setlocale(LC_NUMERIC, saved_locale);
-    if (errno == ERANGE) {
-      // errno must be reset, e.g. see the example here:
-      // https://en.cppreference.com/w/cpp/string/byte/strtof
-      errno = 0;
-      return false;
-    }
-    return end == str + strlen(str);
-  }
-
-  std::unique_ptr<char[]> DToStr(double value) const override {
-    std::stringstream ss;
-    ss.imbue(std::locale("C"));
-    ss << value;
-    std::string str = ss.str();
-    std::unique_ptr<char[]> result(new char[str.size() + 1]);
-    memcpy(result.get(), str.c_str(), str.size() + 1);
-    return result;
-  }
-};
-}  // namespace
-
-Platform* GetLinuxDevPlatform() {
-  static Platform* deps = new LinuxDevPlatform;
-  return deps;
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/linux_dev_platform.h b/third_party/inspector_protocol/encoding/linux_dev_platform.h
deleted file mode 100644
index cf5dfd5b..0000000
--- a/third_party/inspector_protocol/encoding/linux_dev_platform.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_LINUX_DEV_PLATFORM_H_
-#define INSPECTOR_PROTOCOL_ENCODING_LINUX_DEV_PLATFORM_H_
-
-#include "platform.h"
-
-namespace inspector_protocol {
-// Returns an instance of the platform implementation that we're using for
-// development on Linux. This is intended and appropriate for tests for this
-// package, for now.
-Platform* GetLinuxDevPlatform();
-}  // namespace inspector_protocol
-
-#endif  // INSPECTOR_PROTOCOL_ENCODING_LINUX_DEV_PLATFORM_H_
diff --git a/third_party/inspector_protocol/encoding/platform.h b/third_party/inspector_protocol/encoding/platform.h
deleted file mode 100644
index cfd2d5d..0000000
--- a/third_party/inspector_protocol/encoding/platform.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_PLATFORM_H_
-#define INSPECTOR_PROTOCOL_ENCODING_PLATFORM_H_
-
-#include <memory>
-
-namespace inspector_protocol {
-// Client code must provide an instance. Implementation should delegate
-// to whatever is appropriate.
-class Platform {
- public:
-  virtual ~Platform() = default;
-  // Parses |str| into |result|. Returns false iff there are
-  // leftover characters or parsing errors.
-  virtual bool StrToD(const char* str, double* result) const = 0;
-
-  // Prints |value| in a format suitable for JSON.
-  virtual std::unique_ptr<char[]> DToStr(double value) const = 0;
-};
-}  // namespace inspector_protocol
-
-#endif  // INSPECTOR_PROTOCOL_ENCODING_PLATFORM_H_
diff --git a/third_party/inspector_protocol/encoding/span.h b/third_party/inspector_protocol/encoding/span.h
deleted file mode 100644
index 052062cf..0000000
--- a/third_party/inspector_protocol/encoding/span.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_SPAN_H_
-#define INSPECTOR_PROTOCOL_ENCODING_SPAN_H_
-
-#include <cstddef>
-
-namespace inspector_protocol {
-// This template is similar to std::span, which will be included in C++20.  Like
-// std::span it uses ptrdiff_t, which is signed (and thus a bit annoying
-// sometimes when comparing with size_t), but other than this it's much simpler.
-template <typename T>
-class span {
- public:
-  using index_type = std::ptrdiff_t;
-
-  span() : data_(nullptr), size_(0) {}
-  span(const T* data, index_type size) : data_(data), size_(size) {}
-
-  const T* data() const { return data_; }
-
-  const T* begin() const { return data_; }
-  const T* end() const { return data_ + size_; }
-
-  const T& operator[](index_type idx) const { return data_[idx]; }
-
-  span<T> subspan(index_type offset, index_type count) const {
-    return span(data_ + offset, count);
-  }
-
-  span<T> subspan(index_type offset) const {
-    return span(data_ + offset, size_ - offset);
-  }
-
-  bool empty() const { return size_ == 0; }
-
-  index_type size() const { return size_; }
-  index_type size_bytes() const { return size_ * sizeof(T); }
-
- private:
-  const T* data_;
-  index_type size_;
-};
-}  // namespace inspector_protocol
-#endif  // INSPECTOR_PROTOCOL_ENCODING_SPAN_H_
diff --git a/third_party/inspector_protocol/encoding/span_test.cc b/third_party/inspector_protocol/encoding/span_test.cc
deleted file mode 100644
index 48ee76d..0000000
--- a/third_party/inspector_protocol/encoding/span_test.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "span.h"
-
-#include "gtest/gtest.h"
-
-namespace inspector_protocol {
-template <typename T>
-class SpanTest : public ::testing::Test {};
-
-using TestTypes = ::testing::Types<uint8_t, uint16_t>;
-TYPED_TEST_SUITE(SpanTest, TestTypes);
-
-TYPED_TEST(SpanTest, Empty) {
-  span<TypeParam> empty;
-  EXPECT_TRUE(empty.empty());
-  EXPECT_EQ(0, empty.size());
-  EXPECT_EQ(0, empty.size_bytes());
-  EXPECT_EQ(empty.begin(), empty.end());
-}
-
-TYPED_TEST(SpanTest, SingleItem) {
-  TypeParam single_item = 42;
-  span<TypeParam> singular(&single_item, 1);
-  EXPECT_FALSE(singular.empty());
-  EXPECT_EQ(1, singular.size());
-  EXPECT_EQ(sizeof(TypeParam), static_cast<size_t>(singular.size_bytes()));
-  EXPECT_EQ(singular.begin() + 1, singular.end());
-  EXPECT_EQ(42, singular[0]);
-}
-
-TYPED_TEST(SpanTest, FiveItems) {
-  std::vector<TypeParam> test_input = {31, 32, 33, 34, 35};
-  span<TypeParam> five_items(test_input.data(), 5);
-  EXPECT_FALSE(five_items.empty());
-  EXPECT_EQ(5, five_items.size());
-  EXPECT_EQ(sizeof(TypeParam) * 5,
-            static_cast<size_t>(five_items.size_bytes()));
-  EXPECT_EQ(five_items.begin() + 5, five_items.end());
-  EXPECT_EQ(31, five_items[0]);
-  EXPECT_EQ(32, five_items[1]);
-  EXPECT_EQ(33, five_items[2]);
-  EXPECT_EQ(34, five_items[3]);
-  EXPECT_EQ(35, five_items[4]);
-  span<TypeParam> three_items = five_items.subspan(2);
-  EXPECT_EQ(3, three_items.size());
-  EXPECT_EQ(33, three_items[0]);
-  EXPECT_EQ(34, three_items[1]);
-  EXPECT_EQ(35, three_items[2]);
-  span<TypeParam> two_items = five_items.subspan(2, 2);
-  EXPECT_EQ(2, two_items.size());
-  EXPECT_EQ(33, two_items[0]);
-  EXPECT_EQ(34, two_items[1]);
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/status.h b/third_party/inspector_protocol/encoding/status.h
deleted file mode 100644
index ea4a3da..0000000
--- a/third_party/inspector_protocol/encoding/status.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_STATUS_H_
-#define INSPECTOR_PROTOCOL_ENCODING_STATUS_H_
-
-#include <cstdint>
-
-namespace inspector_protocol {
-// Error codes.
-enum class Error {
-  OK = 0,
-  // JSON parsing errors - json_parser.{h,cc}.
-  JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
-  JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
-  JSON_PARSER_NO_INPUT = 0x03,
-  JSON_PARSER_INVALID_TOKEN = 0x04,
-  JSON_PARSER_INVALID_NUMBER = 0x05,
-  JSON_PARSER_INVALID_STRING = 0x06,
-  JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07,
-  JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08,
-  JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09,
-  JSON_PARSER_COLON_EXPECTED = 0x0a,
-  JSON_PARSER_UNEXPECTED_OBJECT_END = 0x0b,
-  JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED = 0x0c,
-  JSON_PARSER_VALUE_EXPECTED = 0x0d,
-
-  CBOR_INVALID_INT32 = 0x0e,
-  CBOR_INVALID_DOUBLE = 0x0f,
-  CBOR_INVALID_ENVELOPE = 0x10,
-  CBOR_INVALID_STRING8 = 0x11,
-  CBOR_INVALID_STRING16 = 0x12,
-  CBOR_INVALID_BINARY = 0x13,
-  CBOR_UNSUPPORTED_VALUE = 0x14,
-  CBOR_NO_INPUT = 0x15,
-  CBOR_INVALID_START_BYTE = 0x16,
-  CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17,
-  CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18,
-  CBOR_UNEXPECTED_EOF_IN_MAP = 0x19,
-  CBOR_INVALID_MAP_KEY = 0x1a,
-  CBOR_STACK_LIMIT_EXCEEDED = 0x1b,
-  CBOR_STRING8_MUST_BE_7BIT = 0x1c,
-  CBOR_TRAILING_JUNK = 0x1d,
-  CBOR_MAP_START_EXPECTED = 0x1e,
-};
-
-// A status value with position that can be copied. The default status
-// is OK. Usually, error status values should come with a valid position.
-struct Status {
-  static constexpr std::ptrdiff_t npos() { return -1; }
-
-  bool ok() const { return error == Error::OK; }
-
-  Error error = Error::OK;
-  std::ptrdiff_t pos = npos();
-  Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
-  Status() = default;
-};
-}  // namespace inspector_protocol
-#endif  // INSPECTOR_PROTOCOL_ENCODING_STATUS_H_
diff --git a/third_party/inspector_protocol/encoding/str_util.cc b/third_party/inspector_protocol/encoding/str_util.cc
deleted file mode 100644
index 1f4be7c..0000000
--- a/third_party/inspector_protocol/encoding/str_util.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "str_util.h"
-
-#include <cstring>
-
-namespace inspector_protocol {
-bool StrEq(span<uint8_t> left, span<uint8_t> right) {
-  return left.size() == right.size() &&
-         0 == memcmp(left.data(), right.data(), left.size());
-}
-
-bool StrEq(span<uint8_t> left, const char* null_terminated_right) {
-  return static_cast<std::size_t>(left.size()) ==
-             strlen(null_terminated_right) &&
-         0 == memcmp(left.data(), null_terminated_right, left.size());
-}
-}  // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/str_util.h b/third_party/inspector_protocol/encoding/str_util.h
deleted file mode 100644
index f377541..0000000
--- a/third_party/inspector_protocol/encoding/str_util.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef INSPECTOR_PROTOCOL_ENCODING_STR_UTIL_H_
-#define INSPECTOR_PROTOCOL_ENCODING_STR_UTIL_H_
-
-#include <cstdint>
-
-#include "span.h"
-
-namespace inspector_protocol {
-// Returns true iff |left| and right have the same contents, byte for byte.
-bool StrEq(span<uint8_t> left, span<uint8_t> right);
-bool StrEq(span<uint8_t> left, const char* null_terminated_right);
-}  // namespace inspector_protocol
-#endif  // INSPECTOR_PROTOCOL_ENCODING_STR_UTIL_H_
diff --git a/third_party/inspector_protocol/inspector_protocol.gni b/third_party/inspector_protocol/inspector_protocol.gni
index ecee942..d612fb6a 100644
--- a/third_party/inspector_protocol/inspector_protocol.gni
+++ b/third_party/inspector_protocol/inspector_protocol.gni
@@ -33,10 +33,10 @@
       invoker.config_file,
       "$inspector_protocol_dir/lib/base_string_adapter_cc.template",
       "$inspector_protocol_dir/lib/base_string_adapter_h.template",
+      "$inspector_protocol_dir/lib/encoding_h.template",
+      "$inspector_protocol_dir/lib/encoding_cpp.template",
       "$inspector_protocol_dir/lib/Allocator_h.template",
       "$inspector_protocol_dir/lib/Array_h.template",
-      "$inspector_protocol_dir/lib/CBOR_h.template",
-      "$inspector_protocol_dir/lib/CBOR_cpp.template",
       "$inspector_protocol_dir/lib/DispatcherBase_cpp.template",
       "$inspector_protocol_dir/lib/DispatcherBase_h.template",
       "$inspector_protocol_dir/lib/ErrorSupport_cpp.template",
diff --git a/third_party/inspector_protocol/inspector_protocol.gypi b/third_party/inspector_protocol/inspector_protocol.gypi
index 3d0a60e..d614474 100644
--- a/third_party/inspector_protocol/inspector_protocol.gypi
+++ b/third_party/inspector_protocol/inspector_protocol.gypi
@@ -5,10 +5,10 @@
 {
   'variables': {
     'inspector_protocol_files': [
+      'lib/encoding_h.template',
+      'lib/encoding_cpp.template',
       'lib/Allocator_h.template',
       'lib/Array_h.template',
-      'lib/CBOR_h.template',
-      'lib/CBOR_cpp.template',
       'lib/DispatcherBase_cpp.template',
       'lib/DispatcherBase_h.template',
       'lib/ErrorSupport_cpp.template',
diff --git a/third_party/inspector_protocol/lib/CBOR_cpp.template b/third_party/inspector_protocol/lib/CBOR_cpp.template
deleted file mode 100644
index d2375b6c..0000000
--- a/third_party/inspector_protocol/lib/CBOR_cpp.template
+++ /dev/null
@@ -1,828 +0,0 @@
-{# This template is generated by gen_cbor_templates.py. #}
-// Generated by lib/CBOR_cpp.template.
-
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#include <cassert>
-#include <limits>
-
-{% for namespace in config.protocol.namespace %}
-namespace {{namespace}} {
-{% endfor %}
-
-// ===== encoding/cbor.cc =====
-
-using namespace cbor;
-
-namespace {
-
-// See RFC 7049 Section 2.3, Table 2.
-static constexpr uint8_t kEncodedTrue =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 21);
-static constexpr uint8_t kEncodedFalse =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 20);
-static constexpr uint8_t kEncodedNull =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 22);
-static constexpr uint8_t kInitialByteForDouble =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 27);
-
-}  // namespace
-
-uint8_t EncodeTrue() { return kEncodedTrue; }
-uint8_t EncodeFalse() { return kEncodedFalse; }
-uint8_t EncodeNull() { return kEncodedNull; }
-
-uint8_t EncodeIndefiniteLengthArrayStart() {
-  return kInitialByteIndefiniteLengthArray;
-}
-
-uint8_t EncodeIndefiniteLengthMapStart() {
-  return kInitialByteIndefiniteLengthMap;
-}
-
-uint8_t EncodeStop() { return kStopByte; }
-
-namespace {
-// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for
-// arbitrary binary data encoded as BYTE_STRING.
-static constexpr uint8_t kExpectedConversionToBase64Tag =
-    EncodeInitialByte(MajorType::TAG, 22);
-
-// When parsing CBOR, we limit recursion depth for objects and arrays
-// to this constant.
-static constexpr int kStackLimit = 1000;
-
-// Writes the bytes for |v| to |out|, starting with the most significant byte.
-// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
-template <typename T>
-void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) {
-  for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes)
-    out->push_back(0xff & (v >> (shift_bytes * 8)));
-}
-}  // namespace
-
-namespace cbor_internals {
-// Writes the start of a token with |type|. The |value| may indicate the size,
-// or it may be the payload if the value is an unsigned integer.
-void WriteTokenStart(MajorType type, uint64_t value,
-                     std::vector<uint8_t>* encoded) {
-  if (value < 24) {
-    // Values 0-23 are encoded directly into the additional info of the
-    // initial byte.
-    encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value));
-    return;
-  }
-  if (value <= std::numeric_limits<uint8_t>::max()) {
-    // Values 24-255 are encoded with one initial byte, followed by the value.
-    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte));
-    encoded->push_back(value);
-    return;
-  }
-  if (value <= std::numeric_limits<uint16_t>::max()) {
-    // Values 256-65535: 1 initial byte + 2 bytes payload.
-    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes));
-    WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded);
-    return;
-  }
-  if (value <= std::numeric_limits<uint32_t>::max()) {
-    // 32 bit uint: 1 initial byte + 4 bytes payload.
-    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes));
-    WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value),
-                                                 encoded);
-    return;
-  }
-  // 64 bit uint: 1 initial byte + 8 bytes payload.
-  encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes));
-  WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded);
-}
-}  // namespace cbor_internals
-
-namespace {
-// Extracts sizeof(T) bytes from |in| to extract a value of type T
-// (e.g. uint64_t, uint32_t, ...), most significant byte first.
-// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
-template <typename T>
-T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
-  assert(static_cast<std::size_t>(in.size()) >= sizeof(T));
-  T result = 0;
-  for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
-    result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
-  return result;
-}
-}  // namespace
-
-namespace cbor_internals {
-int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
-  if (bytes.empty()) return -1;
-  uint8_t initial_byte = bytes[0];
-  *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
-
-  uint8_t additional_information = initial_byte & kAdditionalInformationMask;
-  if (additional_information < 24) {
-    // Values 0-23 are encoded directly into the additional info of the
-    // initial byte.
-    *value = additional_information;
-    return 1;
-  }
-  if (additional_information == kAdditionalInformation1Byte) {
-    // Values 24-255 are encoded with one initial byte, followed by the value.
-    if (bytes.size() < 2) return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
-    return 2;
-  }
-  if (additional_information == kAdditionalInformation2Bytes) {
-    // Values 256-65535: 1 initial byte + 2 bytes payload.
-    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t))
-      return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
-    return 3;
-  }
-  if (additional_information == kAdditionalInformation4Bytes) {
-    // 32 bit uint: 1 initial byte + 4 bytes payload.
-    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t))
-      return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
-    return 5;
-  }
-  if (additional_information == kAdditionalInformation8Bytes) {
-    // 64 bit uint: 1 initial byte + 8 bytes payload.
-    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t))
-      return -1;
-    *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
-    return 9;
-  }
-  return -1;
-}
-}  // namespace cbor_internals
-
-using cbor_internals::WriteTokenStart;
-using cbor_internals::ReadTokenStart;
-
-void EncodeInt32(int32_t value, std::vector<uint8_t>* out) {
-  if (value >= 0) {
-    WriteTokenStart(MajorType::UNSIGNED, value, out);
-  } else {
-    uint64_t representation = static_cast<uint64_t>(-(value + 1));
-    WriteTokenStart(MajorType::NEGATIVE, representation, out);
-  }
-}
-
-void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) {
-  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
-  WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
-  // When emitting UTF16 characters, we always write the least significant byte
-  // first; this is because it's the native representation for X86.
-  // TODO(johannes): Implement a more efficient thing here later, e.g.
-  // casting *iff* the machine has this byte order.
-  // The wire format for UTF16 chars will probably remain the same
-  // (least significant byte first) since this way we can have
-  // golden files, unittests, etc. that port easily and universally.
-  // See also:
-  // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
-  for (const uint16_t two_bytes : in) {
-    out->push_back(two_bytes);
-    out->push_back(two_bytes >> 8);
-  }
-}
-
-void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) {
-  WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(in.size_bytes()),
-                  out);
-  out->insert(out->end(), in.begin(), in.end());
-}
-
-void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) {
-  for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) {
-    if (latin1[ii] <= 127) continue;
-    // If there's at least one non-ASCII char, convert to UTF8.
-    std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii);
-    for (; ii < latin1.size(); ++ii) {
-      if (latin1[ii] <= 127) {
-        utf8.push_back(latin1[ii]);
-      } else {
-        // 0xC0 means it's a UTF8 sequence with 2 bytes.
-        utf8.push_back((latin1[ii] >> 6) | 0xc0);
-        utf8.push_back((latin1[ii] | 0x80) & 0xbf);
-      }
-    }
-    EncodeString8(span<uint8_t>(utf8.data(), utf8.size()), out);
-    return;
-  }
-  EncodeString8(latin1, out);
-}
-
-void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) {
-  // If there's at least one non-ASCII char, encode as STRING16 (UTF16).
-  for (uint16_t ch : utf16) {
-    if (ch <= 127) continue;
-    EncodeString16(utf16, out);
-    return;
-  }
-  // It's all US-ASCII, strip out every second byte and encode as UTF8.
-  WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(utf16.size()), out);
-  out->insert(out->end(), utf16.begin(), utf16.end());
-}
-
-void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) {
-  out->push_back(kExpectedConversionToBase64Tag);
-  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
-  WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
-  out->insert(out->end(), in.begin(), in.end());
-}
-
-// A double is encoded with a specific initial byte
-// (kInitialByteForDouble) plus the 64 bits of payload for its value.
-constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
-
-// An envelope is encoded with a specific initial byte
-// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
-// bit wide length, plus a 32 bit length for that string.
-constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
-
-void EncodeDouble(double value, std::vector<uint8_t>* out) {
-  // The additional_info=27 indicates 64 bits for the double follow.
-  // See RFC 7049 Section 2.3, Table 1.
-  out->push_back(kInitialByteForDouble);
-  union {
-    double from_double;
-    uint64_t to_uint64;
-  } reinterpret;
-  reinterpret.from_double = value;
-  WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out);
-}
-
-void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) {
-  assert(byte_size_pos_ == 0);
-  out->push_back(kInitialByteForEnvelope);
-  out->push_back(kInitialByteFor32BitLengthByteString);
-  byte_size_pos_ = out->size();
-  out->resize(out->size() + sizeof(uint32_t));
-}
-
-bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) {
-  assert(byte_size_pos_ != 0);
-  // The byte size is the size of the payload, that is, all the
-  // bytes that were written past the byte size position itself.
-  uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t));
-  // We store exactly 4 bytes, so at most INT32MAX, with most significant
-  // byte first.
-  if (byte_size > std::numeric_limits<uint32_t>::max()) return false;
-  for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0;
-       --shift_bytes) {
-    (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8));
-  }
-  return true;
-}
-
-namespace {
-class JSONToCBOREncoder : public JSONParserHandler {
- public:
-  JSONToCBOREncoder(std::vector<uint8_t>* out, Status* status)
-      : out_(out), status_(status) {
-    *status_ = Status();
-  }
-
-  void HandleObjectBegin() override {
-    envelopes_.emplace_back();
-    envelopes_.back().EncodeStart(out_);
-    out_->push_back(kInitialByteIndefiniteLengthMap);
-  }
-
-  void HandleObjectEnd() override {
-    out_->push_back(kStopByte);
-    assert(!envelopes_.empty());
-    envelopes_.back().EncodeStop(out_);
-    envelopes_.pop_back();
-  }
-
-  void HandleArrayBegin() override {
-    envelopes_.emplace_back();
-    envelopes_.back().EncodeStart(out_);
-    out_->push_back(kInitialByteIndefiniteLengthArray);
-  }
-
-  void HandleArrayEnd() override {
-    out_->push_back(kStopByte);
-    assert(!envelopes_.empty());
-    envelopes_.back().EncodeStop(out_);
-    envelopes_.pop_back();
-  }
-
-  void HandleString8(span<uint8_t> chars) override {
-    EncodeString8(chars, out_);
-  }
-
-  void HandleString16(span<uint16_t> chars) override {
-    for (uint16_t ch : chars) {
-      if (ch >= 0x7f) {
-        // If there's at least one non-7bit character, we encode as UTF16.
-        EncodeString16(chars, out_);
-        return;
-      }
-    }
-    std::vector<uint8_t> sevenbit_chars(chars.begin(), chars.end());
-    EncodeString8(span<uint8_t>(sevenbit_chars.data(), sevenbit_chars.size()),
-                  out_);
-  }
-
-  void HandleBinary(std::vector<uint8_t> bytes) override {
-    EncodeBinary(span<uint8_t>(bytes.data(), bytes.size()), out_);
-  }
-
-  void HandleDouble(double value) override { EncodeDouble(value, out_); }
-
-  void HandleInt32(int32_t value) override { EncodeInt32(value, out_); }
-
-  void HandleBool(bool value) override {
-    // See RFC 7049 Section 2.3, Table 2.
-    out_->push_back(value ? kEncodedTrue : kEncodedFalse);
-  }
-
-  void HandleNull() override {
-    // See RFC 7049 Section 2.3, Table 2.
-    out_->push_back(kEncodedNull);
-  }
-
-  void HandleError(Status error) override {
-    assert(!error.ok());
-    *status_ = error;
-    out_->clear();
-  }
-
- private:
-  std::vector<uint8_t>* out_;
-  std::vector<EnvelopeEncoder> envelopes_;
-  Status* status_;
-};
-}  // namespace
-
-std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder(
-    std::vector<uint8_t>* out, Status* status) {
-  return std::unique_ptr<JSONParserHandler>(new JSONToCBOREncoder(out, status));
-}
-
-namespace {
-// Below are three parsing routines for CBOR, which cover enough
-// to roundtrip JSON messages.
-bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer,
-              JSONParserHandler* out);
-bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out);
-bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out);
-
-void ParseUTF16String(CBORTokenizer* tokenizer, JSONParserHandler* out) {
-  std::vector<uint16_t> value;
-  span<uint8_t> rep = tokenizer->GetString16WireRep();
-  for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2)
-    value.push_back((rep[ii + 1] << 8) | rep[ii]);
-  out->HandleString16(span<uint16_t>(value.data(), value.size()));
-  tokenizer->Next();
-}
-
-bool ParseUTF8String(CBORTokenizer* tokenizer, JSONParserHandler* out) {
-  assert(tokenizer->TokenTag() == CBORTokenTag::STRING8);
-  out->HandleString8(tokenizer->GetString8());
-  tokenizer->Next();
-  return true;
-}
-
-bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out) {
-  if (stack_depth > kStackLimit) {
-    out->HandleError(
-        Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos});
-    return false;
-  }
-  // Skip past the envelope to get to what's inside.
-  if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE)
-    tokenizer->EnterEnvelope();
-  switch (tokenizer->TokenTag()) {
-    case CBORTokenTag::ERROR_VALUE:
-      out->HandleError(tokenizer->Status());
-      return false;
-    case CBORTokenTag::DONE:
-      out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
-                              tokenizer->Status().pos});
-      return false;
-    case CBORTokenTag::TRUE_VALUE:
-      out->HandleBool(true);
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::FALSE_VALUE:
-      out->HandleBool(false);
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::NULL_VALUE:
-      out->HandleNull();
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::INT32:
-      out->HandleInt32(tokenizer->GetInt32());
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::DOUBLE:
-      out->HandleDouble(tokenizer->GetDouble());
-      tokenizer->Next();
-      return true;
-    case CBORTokenTag::STRING8:
-      return ParseUTF8String(tokenizer, out);
-    case CBORTokenTag::STRING16:
-      ParseUTF16String(tokenizer, out);
-      return true;
-    case CBORTokenTag::BINARY: {
-      span<uint8_t> binary = tokenizer->GetBinary();
-      out->HandleBinary(std::vector<uint8_t>(binary.begin(), binary.end()));
-      tokenizer->Next();
-      return true;
-    }
-    case CBORTokenTag::MAP_START:
-      return ParseMap(stack_depth + 1, tokenizer, out);
-    case CBORTokenTag::ARRAY_START:
-      return ParseArray(stack_depth + 1, tokenizer, out);
-    default:
-      out->HandleError(
-          Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos});
-      return false;
-  }
-}
-
-// |bytes| must start with the indefinite length array byte, so basically,
-// ParseArray may only be called after an indefinite length array has been
-// detected.
-bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer,
-                JSONParserHandler* out) {
-  assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
-  tokenizer->Next();
-  out->HandleArrayBegin();
-  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
-    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
-      out->HandleError(
-          Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos});
-      return false;
-    }
-    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
-      out->HandleError(tokenizer->Status());
-      return false;
-    }
-    // Parse value.
-    if (!ParseValue(stack_depth, tokenizer, out)) return false;
-  }
-  out->HandleArrayEnd();
-  tokenizer->Next();
-  return true;
-}
-
-// |bytes| must start with the indefinite length array byte, so basically,
-// ParseArray may only be called after an indefinite length array has been
-// detected.
-bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer,
-              JSONParserHandler* out) {
-  assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START);
-  out->HandleObjectBegin();
-  tokenizer->Next();
-  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
-    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
-      out->HandleError(
-          Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos});
-      return false;
-    }
-    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
-      out->HandleError(tokenizer->Status());
-      return false;
-    }
-    // Parse key.
-    if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
-      if (!ParseUTF8String(tokenizer, out)) return false;
-    } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
-      ParseUTF16String(tokenizer, out);
-    } else {
-      out->HandleError(
-          Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos});
-      return false;
-    }
-    // Parse value.
-    if (!ParseValue(stack_depth, tokenizer, out)) return false;
-  }
-  out->HandleObjectEnd();
-  tokenizer->Next();
-  return true;
-}
-}  // namespace
-
-void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out) {
-  if (bytes.empty()) {
-    json_out->HandleError(Status{Error::CBOR_NO_INPUT, 0});
-    return;
-  }
-  if (bytes[0] != kInitialByteForEnvelope) {
-    json_out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0});
-    return;
-  }
-  CBORTokenizer tokenizer(bytes);
-  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
-    json_out->HandleError(tokenizer.Status());
-    return;
-  }
-  // We checked for the envelope start byte above, so the tokenizer
-  // must agree here, since it's not an error.
-  assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE);
-  tokenizer.EnterEnvelope();
-  if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) {
-    json_out->HandleError(
-        Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos});
-    return;
-  }
-  if (!ParseMap(/*stack_depth=*/1, &tokenizer, json_out)) return;
-  if (tokenizer.TokenTag() == CBORTokenTag::DONE) return;
-  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
-    json_out->HandleError(tokenizer.Status());
-    return;
-  }
-  json_out->HandleError(
-      Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos});
-}
-
-CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) {
-  ReadNextToken(/*enter_envelope=*/false);
-}
-CBORTokenizer::~CBORTokenizer() {}
-
-CBORTokenTag CBORTokenizer::TokenTag() const { return token_tag_; }
-
-void CBORTokenizer::Next() {
-  if (token_tag_ == CBORTokenTag::ERROR_VALUE || token_tag_ == CBORTokenTag::DONE)
-    return;
-  ReadNextToken(/*enter_envelope=*/false);
-}
-
-void CBORTokenizer::EnterEnvelope() {
-  assert(token_tag_ == CBORTokenTag::ENVELOPE);
-  ReadNextToken(/*enter_envelope=*/true);
-}
-
-Status CBORTokenizer::Status() const { return status_; }
-
-int32_t CBORTokenizer::GetInt32() const {
-  assert(token_tag_ == CBORTokenTag::INT32);
-  // The range checks happen in ::ReadNextToken().
-  return static_cast<uint32_t>(
-      token_start_type_ == MajorType::UNSIGNED
-          ? token_start_internal_value_
-          : -static_cast<int64_t>(token_start_internal_value_) - 1);
-}
-
-double CBORTokenizer::GetDouble() const {
-  assert(token_tag_ == CBORTokenTag::DOUBLE);
-  union {
-    uint64_t from_uint64;
-    double to_double;
-  } reinterpret;
-  reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>(
-      bytes_.subspan(status_.pos + 1));
-  return reinterpret.to_double;
-}
-
-span<uint8_t> CBORTokenizer::GetString8() const {
-  assert(token_tag_ == CBORTokenTag::STRING8);
-  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
-}
-
-span<uint8_t> CBORTokenizer::GetString16WireRep() const {
-  assert(token_tag_ == CBORTokenTag::STRING16);
-  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
-}
-
-span<uint8_t> CBORTokenizer::GetBinary() const {
-  assert(token_tag_ == CBORTokenTag::BINARY);
-  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
-}
-
-void CBORTokenizer::ReadNextToken(bool enter_envelope) {
-  if (enter_envelope) {
-    status_.pos += kEncodedEnvelopeHeaderSize;
-  } else {
-    status_.pos =
-        status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_;
-  }
-  status_.error = Error::OK;
-  if (status_.pos >= bytes_.size()) {
-    token_tag_ = CBORTokenTag::DONE;
-    return;
-  }
-  switch (bytes_[status_.pos]) {
-    case kStopByte:
-      SetToken(CBORTokenTag::STOP, 1);
-      return;
-    case kInitialByteIndefiniteLengthMap:
-      SetToken(CBORTokenTag::MAP_START, 1);
-      return;
-    case kInitialByteIndefiniteLengthArray:
-      SetToken(CBORTokenTag::ARRAY_START, 1);
-      return;
-    case kEncodedTrue:
-      SetToken(CBORTokenTag::TRUE_VALUE, 1);
-      return;
-    case kEncodedFalse:
-      SetToken(CBORTokenTag::FALSE_VALUE, 1);
-      return;
-    case kEncodedNull:
-      SetToken(CBORTokenTag::NULL_VALUE, 1);
-      return;
-    case kExpectedConversionToBase64Tag: {  // BINARY
-      int8_t bytes_read =
-          ReadTokenStart(bytes_.subspan(status_.pos + 1), &token_start_type_,
-                         &token_start_internal_value_);
-      int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_;
-      if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
-          status_.pos + token_byte_length > bytes_.size()) {
-        SetError(Error::CBOR_INVALID_BINARY);
-        return;
-      }
-      SetToken(CBORTokenTag::BINARY,
-               static_cast<std::ptrdiff_t>(token_byte_length));
-      return;
-    }
-    case kInitialByteForDouble: {  // DOUBLE
-      if (status_.pos + kEncodedDoubleSize > bytes_.size()) {
-        SetError(Error::CBOR_INVALID_DOUBLE);
-        return;
-      }
-      SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize);
-      return;
-    }
-    case kInitialByteForEnvelope: {  // ENVELOPE
-      if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) {
-        SetError(Error::CBOR_INVALID_ENVELOPE);
-        return;
-      }
-      // The envelope must be a byte string with 32 bit length.
-      if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) {
-        SetError(Error::CBOR_INVALID_ENVELOPE);
-        return;
-      }
-      // Read the length of the byte string.
-      token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
-          bytes_.subspan(status_.pos + 2));
-      // Make sure the payload is contained within the message.
-      if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize +
-              status_.pos >
-          static_cast<std::size_t>(bytes_.size())) {
-        SetError(Error::CBOR_INVALID_ENVELOPE);
-        return;
-      }
-      auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-      SetToken(CBORTokenTag::ENVELOPE,
-               kEncodedEnvelopeHeaderSize + length);
-      return;
-    }
-    default: {
-      span<uint8_t> remainder =
-          bytes_.subspan(status_.pos, bytes_.size() - status_.pos);
-      assert(!remainder.empty());
-      int8_t token_start_length = ReadTokenStart(remainder, &token_start_type_,
-                                                 &token_start_internal_value_);
-      bool success = token_start_length != -1;
-      switch (token_start_type_) {
-        case MajorType::UNSIGNED:  // INT32.
-          if (!success || std::numeric_limits<int32_t>::max() <
-                              token_start_internal_value_) {
-            SetError(Error::CBOR_INVALID_INT32);
-            return;
-          }
-          SetToken(CBORTokenTag::INT32, token_start_length);
-          return;
-        case MajorType::NEGATIVE:  // INT32.
-          if (!success ||
-              std::numeric_limits<int32_t>::min() >
-                  -static_cast<int64_t>(token_start_internal_value_) - 1) {
-            SetError(Error::CBOR_INVALID_INT32);
-            return;
-          }
-          SetToken(CBORTokenTag::INT32, token_start_length);
-          return;
-        case MajorType::STRING: {  // STRING8.
-          if (!success || remainder.size() < static_cast<int64_t>(
-                                                 token_start_internal_value_)) {
-            SetError(Error::CBOR_INVALID_STRING8);
-            return;
-          }
-          auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-          SetToken(CBORTokenTag::STRING8, token_start_length + length);
-          return;
-        }
-        case MajorType::BYTE_STRING: {  // STRING16.
-          if (!success ||
-              remainder.size() <
-                  static_cast<int64_t>(token_start_internal_value_) ||
-              // Must be divisible by 2 since UTF16 is 2 bytes per character.
-              token_start_internal_value_ & 1) {
-            SetError(Error::CBOR_INVALID_STRING16);
-            return;
-          }
-          auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
-          SetToken(CBORTokenTag::STRING16, token_start_length + length);
-          return;
-        }
-        case MajorType::ARRAY:
-        case MajorType::MAP:
-        case MajorType::TAG:
-        case MajorType::SIMPLE_VALUE:
-          SetError(Error::CBOR_UNSUPPORTED_VALUE);
-          return;
-      }
-    }
-  }
-}
-
-void CBORTokenizer::SetToken(CBORTokenTag token_tag,
-                             std::ptrdiff_t token_byte_length) {
-  token_tag_ = token_tag;
-  token_byte_length_ = token_byte_length;
-}
-
-void CBORTokenizer::SetError(Error error) {
-  token_tag_ = CBORTokenTag::ERROR_VALUE;
-  status_.error = error;
-}
-
-#if 0
-void DumpCBOR(span<uint8_t> cbor) {
-  std::string indent;
-  CBORTokenizer tokenizer(cbor);
-  while (true) {
-    fprintf(stderr, "%s", indent.c_str());
-    switch (tokenizer.TokenTag()) {
-      case CBORTokenTag::ERROR_VALUE:
-        fprintf(stderr, "ERROR {status.error=%d, status.pos=%ld}\n",
-               tokenizer.Status().error, tokenizer.Status().pos);
-        return;
-      case CBORTokenTag::DONE:
-        fprintf(stderr, "DONE\n");
-        return;
-      case CBORTokenTag::TRUE_VALUE:
-        fprintf(stderr, "TRUE_VALUE\n");
-        break;
-      case CBORTokenTag::FALSE_VALUE:
-        fprintf(stderr, "FALSE_VALUE\n");
-        break;
-      case CBORTokenTag::NULL_VALUE:
-        fprintf(stderr, "NULL_VALUE\n");
-        break;
-      case CBORTokenTag::INT32:
-        fprintf(stderr, "INT32 [%d]\n", tokenizer.GetInt32());
-        break;
-      case CBORTokenTag::DOUBLE:
-        fprintf(stderr, "DOUBLE [%lf]\n", tokenizer.GetDouble());
-        break;
-      case CBORTokenTag::STRING8: {
-        span<uint8_t> v = tokenizer.GetString8();
-        std::string t(v.begin(), v.end());
-        fprintf(stderr, "STRING8 [%s]\n", t.c_str());
-        break;
-      }
-      case CBORTokenTag::STRING16: {
-        span<uint8_t> v = tokenizer.GetString16WireRep();
-        std::string t(v.begin(), v.end());
-        fprintf(stderr, "STRING16 [%s]\n", t.c_str());
-        break;
-      }
-      case CBORTokenTag::BINARY: {
-        span<uint8_t> v = tokenizer.GetBinary();
-        std::string t(v.begin(), v.end());
-        fprintf(stderr, "BINARY [%s]\n", t.c_str());
-        break;
-      }
-      case CBORTokenTag::MAP_START:
-        fprintf(stderr, "MAP_START\n");
-        indent += "  ";
-        break;
-      case CBORTokenTag::ARRAY_START:
-        fprintf(stderr, "ARRAY_START\n");
-        indent += "  ";
-        break;
-      case CBORTokenTag::STOP:
-        fprintf(stderr, "STOP\n");
-        indent.erase(0, 2);
-        break;
-      case CBORTokenTag::ENVELOPE:
-        fprintf(stderr, "ENVELOPE\n");
-        tokenizer.EnterEnvelope();
-        continue;
-    }
-    tokenizer.Next();
-  }
-}
-#endif
-
-
-{% for namespace in config.protocol.namespace %}
-} // namespace {{namespace}}
-{% endfor %}
-
diff --git a/third_party/inspector_protocol/lib/Values_cpp.template b/third_party/inspector_protocol/lib/Values_cpp.template
index 20899a3..2d4463e2 100644
--- a/third_party/inspector_protocol/lib/Values_cpp.template
+++ b/third_party/inspector_protocol/lib/Values_cpp.template
@@ -66,21 +66,21 @@
 
 // Below are three parsing routines for CBOR, which cover enough
 // to roundtrip JSON messages.
-std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, CBORTokenizer* tokenizer);
-std::unique_ptr<ListValue> parseArray(int32_t stack_depth, CBORTokenizer* tokenizer);
-std::unique_ptr<Value> parseValue(int32_t stack_depth, CBORTokenizer* tokenizer);
+std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);
+std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);
+std::unique_ptr<Value> parseValue(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);
 
 // |bytes| must start with the indefinite length array byte, so basically,
 // ParseArray may only be called after an indefinite length array has been
 // detected.
-std::unique_ptr<ListValue> parseArray(int32_t stack_depth, CBORTokenizer* tokenizer) {
-  DCHECK(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
+std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer) {
+  DCHECK(tokenizer->TokenTag() == cbor::CBORTokenTag::ARRAY_START);
   tokenizer->Next();
   auto list = ListValue::create();
-  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
+  while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) {
     // Error::CBOR_UNEXPECTED_EOF_IN_ARRAY
-    if (tokenizer->TokenTag() == CBORTokenTag::DONE) return nullptr;
-    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr;
+    if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) return nullptr;
+    if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
     // Parse value.
     auto value = parseValue(stack_depth, tokenizer);
     if (!value) return nullptr;
@@ -91,51 +91,51 @@
 }
 
 std::unique_ptr<Value> parseValue(
-    int32_t stack_depth, CBORTokenizer* tokenizer) {
+    int32_t stack_depth, cbor::CBORTokenizer* tokenizer) {
   // Error::CBOR_STACK_LIMIT_EXCEEDED
   if (stack_depth > kStackLimitValues) return nullptr;
   // Skip past the envelope to get to what's inside.
-  if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE)
+  if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE)
     tokenizer->EnterEnvelope();
   switch (tokenizer->TokenTag()) {
-    case CBORTokenTag::ERROR_VALUE:
+    case cbor::CBORTokenTag::ERROR_VALUE:
       return nullptr;
-    case CBORTokenTag::DONE:
+    case cbor::CBORTokenTag::DONE:
       // Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE
       return nullptr;
-    case CBORTokenTag::TRUE_VALUE: {
+    case cbor::CBORTokenTag::TRUE_VALUE: {
       std::unique_ptr<Value> value = FundamentalValue::create(true);
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::FALSE_VALUE: {
+    case cbor::CBORTokenTag::FALSE_VALUE: {
       std::unique_ptr<Value> value = FundamentalValue::create(false);
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::NULL_VALUE: {
+    case cbor::CBORTokenTag::NULL_VALUE: {
       std::unique_ptr<Value> value = FundamentalValue::null();
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::INT32: {
+    case cbor::CBORTokenTag::INT32: {
       std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetInt32());
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::DOUBLE: {
+    case cbor::CBORTokenTag::DOUBLE: {
       std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetDouble());
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::STRING8: {
+    case cbor::CBORTokenTag::STRING8: {
       span<uint8_t> str = tokenizer->GetString8();
       std::unique_ptr<Value> value =
           StringValue::create(StringUtil::fromUTF8(str.data(), str.size()));
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::STRING16: {
+    case cbor::CBORTokenTag::STRING16: {
       span<uint8_t> wire = tokenizer->GetString16WireRep();
       DCHECK_EQ(wire.size() & 1, 0);
       std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF16(
@@ -143,14 +143,14 @@
       tokenizer->Next();
       return value;
     }
-    case CBORTokenTag::BINARY: {
+    case cbor::CBORTokenTag::BINARY: {
       span<uint8_t> payload = tokenizer->GetBinary();
       tokenizer->Next();
       return BinaryValue::create(Binary::fromSpan(payload.data(), payload.size()));
     }
-    case CBORTokenTag::MAP_START:
+    case cbor::CBORTokenTag::MAP_START:
       return parseMap(stack_depth + 1, tokenizer);
-    case CBORTokenTag::ARRAY_START:
+    case cbor::CBORTokenTag::ARRAY_START:
       return parseArray(stack_depth + 1, tokenizer);
     default:
       // Error::CBOR_UNSUPPORTED_VALUE
@@ -162,22 +162,22 @@
 // ParseArray may only be called after an indefinite length array has been
 // detected.
 std::unique_ptr<DictionaryValue> parseMap(
-    int32_t stack_depth, CBORTokenizer* tokenizer) {
+    int32_t stack_depth, cbor::CBORTokenizer* tokenizer) {
   auto dict = DictionaryValue::create();
   tokenizer->Next();
-  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
-    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
+  while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) {
+    if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) {
       // Error::CBOR_UNEXPECTED_EOF_IN_MAP
       return nullptr;
     }
-    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr;
+    if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
     // Parse key.
     String key;
-    if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
+    if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) {
       span<uint8_t> key_span = tokenizer->GetString8();
       key = StringUtil::fromUTF8(key_span.data(), key_span.size());
       tokenizer->Next();
-    } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
+    } else if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) {
       return nullptr;  // STRING16 not supported yet.
     } else {
       // Error::CBOR_INVALID_MAP_KEY
@@ -202,22 +202,21 @@
   if (bytes.empty()) return nullptr;
 
   // Error::CBOR_INVALID_START_BYTE
-  // TODO(johannes): EncodeInitialByteForEnvelope() method.
-  if (bytes[0] != 0xd8) return nullptr;
+  if (bytes[0] != cbor::InitialByteForEnvelope()) return nullptr;
 
-  CBORTokenizer tokenizer(bytes);
-  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr;
+  cbor::CBORTokenizer tokenizer(bytes);
+  if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
 
   // We checked for the envelope start byte above, so the tokenizer
   // must agree here, since it's not an error.
-  DCHECK(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE);
+  DCHECK(tokenizer.TokenTag() == cbor::CBORTokenTag::ENVELOPE);
   tokenizer.EnterEnvelope();
   // Error::MAP_START_EXPECTED
-  if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) return nullptr;
+  if (tokenizer.TokenTag() != cbor::CBORTokenTag::MAP_START) return nullptr;
   std::unique_ptr<Value> result = parseMap(/*stack_depth=*/1, &tokenizer);
   if (!result) return nullptr;
-  if (tokenizer.TokenTag() == CBORTokenTag::DONE) return result;
-  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr;
+  if (tokenizer.TokenTag() == cbor::CBORTokenTag::DONE) return result;
+  if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr;
   // Error::CBOR_TRAILING_JUNK
   return nullptr;
 }
@@ -255,7 +254,7 @@
 
 void Value::writeBinary(std::vector<uint8_t>* bytes) const {
     DCHECK(m_type == TypeNull);
-    bytes->push_back(EncodeNull());
+    bytes->push_back(cbor::EncodeNull());
 }
 
 std::unique_ptr<Value> Value::clone() const
@@ -332,13 +331,13 @@
 void FundamentalValue::writeBinary(std::vector<uint8_t>* bytes) const {
     switch (type()) {
     case TypeDouble:
-        EncodeDouble(m_doubleValue, bytes);
+        cbor::EncodeDouble(m_doubleValue, bytes);
         return;
     case TypeInteger:
-        EncodeInt32(m_integerValue, bytes);
+        cbor::EncodeInt32(m_integerValue, bytes);
         return;
     case TypeBoolean:
-        bytes->push_back(m_boolValue ? EncodeTrue() : EncodeFalse());
+        bytes->push_back(m_boolValue ? cbor::EncodeTrue() : cbor::EncodeFalse());
         return;
     default:
         DCHECK(false);
@@ -381,19 +380,19 @@
 //   transcodes to UTF8 if needed.
 void EncodeString(const String& s, std::vector<uint8_t>* out) {
   if (StringUtil::CharacterCount(s) == 0) {
-    EncodeString8(span<uint8_t>(nullptr, 0), out);  // Empty string.
+    cbor::EncodeString8(span<uint8_t>(nullptr, 0), out);  // Empty string.
   } else if (StringUtil::CharactersLatin1(s)) {
-    EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s),
-                                   StringUtil::CharacterCount(s)),
-                     out);
+    cbor::EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s),
+		                         StringUtil::CharacterCount(s)),
+                           out);
   } else if (StringUtil::CharactersUTF16(s)) {
-    EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s),
-                                   StringUtil::CharacterCount(s)),
-                    out);
+    cbor::EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s),
+                                         StringUtil::CharacterCount(s)),
+                          out);
   } else if (StringUtil::CharactersUTF8(s)) {
-    EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s),
-                                StringUtil::CharacterCount(s)),
-                  out);
+    cbor::EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s),
+                                      StringUtil::CharacterCount(s)),
+                        out);
   }
 }
 }  // namespace
@@ -420,7 +419,8 @@
 }
 
 void BinaryValue::writeBinary(std::vector<uint8_t>* bytes) const {
-    EncodeBinary(span<uint8_t>(m_binaryValue.data(), m_binaryValue.size()), bytes);
+    cbor::EncodeBinary(span<uint8_t>(m_binaryValue.data(),
+                                     m_binaryValue.size()), bytes);
 }
 
 std::unique_ptr<Value> BinaryValue::clone() const
@@ -583,9 +583,9 @@
 }
 
 void DictionaryValue::writeBinary(std::vector<uint8_t>* bytes) const {
-    EnvelopeEncoder encoder;
+    cbor::EnvelopeEncoder encoder;
     encoder.EncodeStart(bytes);
-    bytes->push_back(EncodeIndefiniteLengthMapStart());
+    bytes->push_back(cbor::EncodeIndefiniteLengthMapStart());
     for (size_t i = 0; i < m_order.size(); ++i) {
         const String& key = m_order[i];
         Dictionary::const_iterator value = m_data.find(key);
@@ -593,7 +593,7 @@
         EncodeString(key, bytes);
         value->second->writeBinary(bytes);
     }
-    bytes->push_back(EncodeStop());
+    bytes->push_back(cbor::EncodeStop());
     encoder.EncodeStop(bytes);
 }
 
@@ -632,13 +632,13 @@
 }
 
 void ListValue::writeBinary(std::vector<uint8_t>* bytes) const {
-    EnvelopeEncoder encoder;
+    cbor::EnvelopeEncoder encoder;
     encoder.EncodeStart(bytes);
-    bytes->push_back(EncodeIndefiniteLengthArrayStart());
+    bytes->push_back(cbor::EncodeIndefiniteLengthArrayStart());
     for (size_t i = 0; i < m_data.size(); ++i) {
         m_data[i]->writeBinary(bytes);
     }
-    bytes->push_back(EncodeStop());
+    bytes->push_back(cbor::EncodeStop());
     encoder.EncodeStop(bytes);
 }
 
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
index 24855d4..94bcd88 100644
--- a/third_party/inspector_protocol/lib/base_string_adapter_cc.template
+++ b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
@@ -256,34 +256,34 @@
   if (in.size() < 1 + 1 + 4 + 1 + 1)
     return false;
   const uint8_t* envelope = reinterpret_cast<const uint8_t*>(in.data());
-  if (cbor::kInitialByteForEnvelope != envelope[0])
+  if (cbor::InitialByteForEnvelope() != envelope[0])
     return false;
-  if (cbor::kInitialByteFor32BitLengthByteString != envelope[1])
+  if (cbor::InitialByteFor32BitLengthByteString() != envelope[1])
     return false;
-  if (cbor::kInitialByteIndefiniteLengthMap != envelope[6])
+  if (cbor::EncodeIndefiniteLengthMapStart() != envelope[6])
     return false;
 
   uint32_t envelope_size = ReadEnvelopeSize(envelope + 2);
   if (envelope_size + 2 + 4 != in.size())
     return false;
-  if (cbor::kStopByte != static_cast<uint8_t>(*in.rbegin()))
+  if (cbor::EncodeStop() != static_cast<uint8_t>(*in.rbegin()))
     return false;
 
   std::vector<uint8_t> encoded_entry;
   encoded_entry.reserve(1 + 4 + key.size() + 1 + 4 + value.size());
   span<uint8_t> key_span(
       reinterpret_cast<const uint8_t*>(key.data()), key.size());
-  EncodeString8(key_span, &encoded_entry);
+  cbor::EncodeString8(key_span, &encoded_entry);
   span<uint8_t> value_span(
       reinterpret_cast<const uint8_t*>(value.data()), value.size());
-  EncodeString8(value_span, &encoded_entry);
+  cbor::EncodeString8(value_span, &encoded_entry);
 
   out->clear();
   out->reserve(in.size() + encoded_entry.size());
   out->append(in.begin(), in.end() - 1);
   out->append(reinterpret_cast<const char*>(encoded_entry.data()),
       encoded_entry.size());
-  out->append(1, static_cast<char>(cbor::kStopByte));
+  out->append(1, static_cast<char>(cbor::EncodeStop()));
   std::size_t new_size = envelope_size + out->size() - in.size();
   if (new_size > static_cast<std::size_t>(
       std::numeric_limits<uint32_t>::max())) {
diff --git a/third_party/inspector_protocol/lib/encoding_cpp.template b/third_party/inspector_protocol/lib/encoding_cpp.template
new file mode 100644
index 0000000..84251d9
--- /dev/null
+++ b/third_party/inspector_protocol/lib/encoding_cpp.template
@@ -0,0 +1,1807 @@
+{# This template is generated by gen_cbor_templates.py. #}
+// Generated by lib/encoding_cpp.template.
+
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#include <cassert>
+#include <cstring>
+#include <limits>
+#include <stack>
+
+{% for namespace in config.protocol.namespace %}
+namespace {{namespace}} {
+{% endfor %}
+
+// ===== encoding/encoding.cc =====
+
+namespace cbor {
+namespace {
+// Indicates the number of bits the "initial byte" needs to be shifted to the
+// right after applying |kMajorTypeMask| to produce the major type in the
+// lowermost bits.
+static constexpr uint8_t kMajorTypeBitShift = 5u;
+// Mask selecting the low-order 5 bits of the "initial byte", which is where
+// the additional information is encoded.
+static constexpr uint8_t kAdditionalInformationMask = 0x1f;
+// Mask selecting the high-order 3 bits of the "initial byte", which indicates
+// the major type of the encoded value.
+static constexpr uint8_t kMajorTypeMask = 0xe0;
+// Indicates the integer is in the following byte.
+static constexpr uint8_t kAdditionalInformation1Byte = 24u;
+// Indicates the integer is in the next 2 bytes.
+static constexpr uint8_t kAdditionalInformation2Bytes = 25u;
+// Indicates the integer is in the next 4 bytes.
+static constexpr uint8_t kAdditionalInformation4Bytes = 26u;
+// Indicates the integer is in the next 8 bytes.
+static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
+
+// Encodes the initial byte, consisting of the |type| in the first 3 bits
+// followed by 5 bits of |additional_info|.
+constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
+  return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
+         (additional_info & kAdditionalInformationMask);
+}
+
+// TAG 24 indicates that what follows is a byte string which is
+// encoded in CBOR format. We use this as a wrapper for
+// maps and arrays, allowing us to skip them, because the
+// byte string carries its size (byte length).
+// https://tools.ietf.org/html/rfc7049#section-2.4.4.1
+static constexpr uint8_t kInitialByteForEnvelope =
+    EncodeInitialByte(MajorType::TAG, 24);
+// The initial byte for a byte string with at most 2^32 bytes
+// of payload. This is used for envelope encoding, even if
+// the byte string is shorter.
+static constexpr uint8_t kInitialByteFor32BitLengthByteString =
+    EncodeInitialByte(MajorType::BYTE_STRING, 26);
+
+// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
+// info = 31.
+static constexpr uint8_t kInitialByteIndefiniteLengthArray =
+    EncodeInitialByte(MajorType::ARRAY, 31);
+static constexpr uint8_t kInitialByteIndefiniteLengthMap =
+    EncodeInitialByte(MajorType::MAP, 31);
+// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
+// length maps / arrays.
+static constexpr uint8_t kStopByte =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
+
+// See RFC 7049 Section 2.3, Table 2.
+static constexpr uint8_t kEncodedTrue =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 21);
+static constexpr uint8_t kEncodedFalse =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 20);
+static constexpr uint8_t kEncodedNull =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 22);
+static constexpr uint8_t kInitialByteForDouble =
+    EncodeInitialByte(MajorType::SIMPLE_VALUE, 27);
+
+// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for
+// arbitrary binary data encoded as BYTE_STRING.
+static constexpr uint8_t kExpectedConversionToBase64Tag =
+    EncodeInitialByte(MajorType::TAG, 22);
+
+// Writes the bytes for |v| to |out|, starting with the most significant byte.
+// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+template <typename T>
+void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) {
+  for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes)
+    out->push_back(0xff & (v >> (shift_bytes * 8)));
+}
+
+// Extracts sizeof(T) bytes from |in| to extract a value of type T
+// (e.g. uint64_t, uint32_t, ...), most significant byte first.
+// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+template <typename T>
+T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
+  assert(static_cast<std::size_t>(in.size()) >= sizeof(T));
+  T result = 0;
+  for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
+    result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
+  return result;
+}
+}  // namespace
+
+namespace internals {
+// Reads the start of a token with definitive size from |bytes|.
+// |type| is the major type as specified in RFC 7049 Section 2.1.
+// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
+// (e.g. for BYTE_STRING).
+// If successful, returns the number of bytes read. Otherwise returns -1.
+int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
+  if (bytes.empty())
+    return -1;
+  uint8_t initial_byte = bytes[0];
+  *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
+
+  uint8_t additional_information = initial_byte & kAdditionalInformationMask;
+  if (additional_information < 24) {
+    // Values 0-23 are encoded directly into the additional info of the
+    // initial byte.
+    *value = additional_information;
+    return 1;
+  }
+  if (additional_information == kAdditionalInformation1Byte) {
+    // Values 24-255 are encoded with one initial byte, followed by the value.
+    if (bytes.size() < 2)
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
+    return 2;
+  }
+  if (additional_information == kAdditionalInformation2Bytes) {
+    // Values 256-65535: 1 initial byte + 2 bytes payload.
+    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t))
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
+    return 3;
+  }
+  if (additional_information == kAdditionalInformation4Bytes) {
+    // 32 bit uint: 1 initial byte + 4 bytes payload.
+    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t))
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
+    return 5;
+  }
+  if (additional_information == kAdditionalInformation8Bytes) {
+    // 64 bit uint: 1 initial byte + 8 bytes payload.
+    if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t))
+      return -1;
+    *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
+    return 9;
+  }
+  return -1;
+}
+
+// Writes the start of a token with |type|. The |value| may indicate the size,
+// or it may be the payload if the value is an unsigned integer.
+void WriteTokenStart(MajorType type,
+                     uint64_t value,
+                     std::vector<uint8_t>* encoded) {
+  if (value < 24) {
+    // Values 0-23 are encoded directly into the additional info of the
+    // initial byte.
+    encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value));
+    return;
+  }
+  if (value <= std::numeric_limits<uint8_t>::max()) {
+    // Values 24-255 are encoded with one initial byte, followed by the value.
+    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte));
+    encoded->push_back(value);
+    return;
+  }
+  if (value <= std::numeric_limits<uint16_t>::max()) {
+    // Values 256-65535: 1 initial byte + 2 bytes payload.
+    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes));
+    WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded);
+    return;
+  }
+  if (value <= std::numeric_limits<uint32_t>::max()) {
+    // 32 bit uint: 1 initial byte + 4 bytes payload.
+    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes));
+    WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value),
+                                                 encoded);
+    return;
+  }
+  // 64 bit uint: 1 initial byte + 8 bytes payload.
+  encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes));
+  WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded);
+}
+}  // namespace internals
+
+// =============================================================================
+// Detecting CBOR content
+// =============================================================================
+
+uint8_t InitialByteForEnvelope() {
+  return kInitialByteForEnvelope;
+}
+uint8_t InitialByteFor32BitLengthByteString() {
+  return kInitialByteFor32BitLengthByteString;
+}
+bool IsCBORMessage(span<uint8_t> msg) {
+  return msg.size() >= 6 && msg[0] == InitialByteForEnvelope() &&
+         msg[1] == InitialByteFor32BitLengthByteString();
+}
+
+// =============================================================================
+// Encoding invidiual CBOR items
+// =============================================================================
+
+uint8_t EncodeTrue() {
+  return kEncodedTrue;
+}
+uint8_t EncodeFalse() {
+  return kEncodedFalse;
+}
+uint8_t EncodeNull() {
+  return kEncodedNull;
+}
+
+uint8_t EncodeIndefiniteLengthArrayStart() {
+  return kInitialByteIndefiniteLengthArray;
+}
+
+uint8_t EncodeIndefiniteLengthMapStart() {
+  return kInitialByteIndefiniteLengthMap;
+}
+
+uint8_t EncodeStop() {
+  return kStopByte;
+}
+
+void EncodeInt32(int32_t value, std::vector<uint8_t>* out) {
+  if (value >= 0) {
+    internals::WriteTokenStart(MajorType::UNSIGNED, value, out);
+  } else {
+    uint64_t representation = static_cast<uint64_t>(-(value + 1));
+    internals::WriteTokenStart(MajorType::NEGATIVE, representation, out);
+  }
+}
+
+void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) {
+  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
+  internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
+  // When emitting UTF16 characters, we always write the least significant byte
+  // first; this is because it's the native representation for X86.
+  // TODO(johannes): Implement a more efficient thing here later, e.g.
+  // casting *iff* the machine has this byte order.
+  // The wire format for UTF16 chars will probably remain the same
+  // (least significant byte first) since this way we can have
+  // golden files, unittests, etc. that port easily and universally.
+  // See also:
+  // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
+  for (const uint16_t two_bytes : in) {
+    out->push_back(two_bytes);
+    out->push_back(two_bytes >> 8);
+  }
+}
+
+void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) {
+  internals::WriteTokenStart(MajorType::STRING,
+                             static_cast<uint64_t>(in.size_bytes()), out);
+  out->insert(out->end(), in.begin(), in.end());
+}
+
+void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) {
+  for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) {
+    if (latin1[ii] <= 127)
+      continue;
+    // If there's at least one non-ASCII char, convert to UTF8.
+    std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii);
+    for (; ii < latin1.size(); ++ii) {
+      if (latin1[ii] <= 127) {
+        utf8.push_back(latin1[ii]);
+      } else {
+        // 0xC0 means it's a UTF8 sequence with 2 bytes.
+        utf8.push_back((latin1[ii] >> 6) | 0xc0);
+        utf8.push_back((latin1[ii] | 0x80) & 0xbf);
+      }
+    }
+    EncodeString8(SpanFromVector(utf8), out);
+    return;
+  }
+  EncodeString8(latin1, out);
+}
+
+void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) {
+  // If there's at least one non-ASCII char, encode as STRING16 (UTF16).
+  for (uint16_t ch : utf16) {
+    if (ch <= 127)
+      continue;
+    EncodeString16(utf16, out);
+    return;
+  }
+  // It's all US-ASCII, strip out every second byte and encode as UTF8.
+  internals::WriteTokenStart(MajorType::STRING,
+                             static_cast<uint64_t>(utf16.size()), out);
+  out->insert(out->end(), utf16.begin(), utf16.end());
+}
+
+void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) {
+  out->push_back(kExpectedConversionToBase64Tag);
+  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
+  internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
+  out->insert(out->end(), in.begin(), in.end());
+}
+
+// A double is encoded with a specific initial byte
+// (kInitialByteForDouble) plus the 64 bits of payload for its value.
+constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
+
+// An envelope is encoded with a specific initial byte
+// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
+// bit wide length, plus a 32 bit length for that string.
+constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
+
+void EncodeDouble(double value, std::vector<uint8_t>* out) {
+  // The additional_info=27 indicates 64 bits for the double follow.
+  // See RFC 7049 Section 2.3, Table 1.
+  out->push_back(kInitialByteForDouble);
+  union {
+    double from_double;
+    uint64_t to_uint64;
+  } reinterpret;
+  reinterpret.from_double = value;
+  WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out);
+}
+
+// =============================================================================
+// cbor::EnvelopeEncoder - for wrapping submessages
+// =============================================================================
+
+void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) {
+  assert(byte_size_pos_ == 0);
+  out->push_back(kInitialByteForEnvelope);
+  out->push_back(kInitialByteFor32BitLengthByteString);
+  byte_size_pos_ = out->size();
+  out->resize(out->size() + sizeof(uint32_t));
+}
+
+bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) {
+  assert(byte_size_pos_ != 0);
+  // The byte size is the size of the payload, that is, all the
+  // bytes that were written past the byte size position itself.
+  uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t));
+  // We store exactly 4 bytes, so at most INT32MAX, with most significant
+  // byte first.
+  if (byte_size > std::numeric_limits<uint32_t>::max())
+    return false;
+  for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0;
+       --shift_bytes) {
+    (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8));
+  }
+  return true;
+}
+
+// =============================================================================
+// cbor::NewCBOREncoder - for encoding from a streaming parser
+// =============================================================================
+
+namespace {
+class CBOREncoder : public StreamingParserHandler {
+ public:
+  CBOREncoder(std::vector<uint8_t>* out, Status* status)
+      : out_(out), status_(status) {
+    *status_ = Status();
+  }
+
+  void HandleMapBegin() override {
+    envelopes_.emplace_back();
+    envelopes_.back().EncodeStart(out_);
+    out_->push_back(kInitialByteIndefiniteLengthMap);
+  }
+
+  void HandleMapEnd() override {
+    out_->push_back(kStopByte);
+    assert(!envelopes_.empty());
+    envelopes_.back().EncodeStop(out_);
+    envelopes_.pop_back();
+  }
+
+  void HandleArrayBegin() override {
+    envelopes_.emplace_back();
+    envelopes_.back().EncodeStart(out_);
+    out_->push_back(kInitialByteIndefiniteLengthArray);
+  }
+
+  void HandleArrayEnd() override {
+    out_->push_back(kStopByte);
+    assert(!envelopes_.empty());
+    envelopes_.back().EncodeStop(out_);
+    envelopes_.pop_back();
+  }
+
+  void HandleString8(span<uint8_t> chars) override {
+    EncodeString8(chars, out_);
+  }
+
+  void HandleString16(span<uint16_t> chars) override {
+    EncodeFromUTF16(chars, out_);
+  }
+
+  void HandleBinary(span<uint8_t> bytes) override { EncodeBinary(bytes, out_); }
+
+  void HandleDouble(double value) override { EncodeDouble(value, out_); }
+
+  void HandleInt32(int32_t value) override { EncodeInt32(value, out_); }
+
+  void HandleBool(bool value) override {
+    // See RFC 7049 Section 2.3, Table 2.
+    out_->push_back(value ? kEncodedTrue : kEncodedFalse);
+  }
+
+  void HandleNull() override {
+    // See RFC 7049 Section 2.3, Table 2.
+    out_->push_back(kEncodedNull);
+  }
+
+  void HandleError(Status error) override {
+    assert(!error.ok());
+    *status_ = error;
+    out_->clear();
+  }
+
+ private:
+  std::vector<uint8_t>* out_;
+  std::vector<EnvelopeEncoder> envelopes_;
+  Status* status_;
+};
+}  // namespace
+
+std::unique_ptr<StreamingParserHandler> NewCBOREncoder(
+    std::vector<uint8_t>* out,
+    Status* status) {
+  return std::unique_ptr<StreamingParserHandler>(new CBOREncoder(out, status));
+}
+
+// =============================================================================
+// cbor::CBORTokenizer - for parsing individual CBOR items
+// =============================================================================
+
+CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) {
+  ReadNextToken(/*enter_envelope=*/false);
+}
+CBORTokenizer::~CBORTokenizer() {}
+
+CBORTokenTag CBORTokenizer::TokenTag() const {
+  return token_tag_;
+}
+
+void CBORTokenizer::Next() {
+  if (token_tag_ == CBORTokenTag::ERROR_VALUE ||
+      token_tag_ == CBORTokenTag::DONE)
+    return;
+  ReadNextToken(/*enter_envelope=*/false);
+}
+
+void CBORTokenizer::EnterEnvelope() {
+  assert(token_tag_ == CBORTokenTag::ENVELOPE);
+  ReadNextToken(/*enter_envelope=*/true);
+}
+
+Status CBORTokenizer::Status() const {
+  return status_;
+}
+
+int32_t CBORTokenizer::GetInt32() const {
+  assert(token_tag_ == CBORTokenTag::INT32);
+  // The range checks happen in ::ReadNextToken().
+  return static_cast<uint32_t>(
+      token_start_type_ == MajorType::UNSIGNED
+          ? token_start_internal_value_
+          : -static_cast<int64_t>(token_start_internal_value_) - 1);
+}
+
+double CBORTokenizer::GetDouble() const {
+  assert(token_tag_ == CBORTokenTag::DOUBLE);
+  union {
+    uint64_t from_uint64;
+    double to_double;
+  } reinterpret;
+  reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>(
+      bytes_.subspan(status_.pos + 1));
+  return reinterpret.to_double;
+}
+
+span<uint8_t> CBORTokenizer::GetString8() const {
+  assert(token_tag_ == CBORTokenTag::STRING8);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
+}
+
+span<uint8_t> CBORTokenizer::GetString16WireRep() const {
+  assert(token_tag_ == CBORTokenTag::STRING16);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
+}
+
+span<uint8_t> CBORTokenizer::GetBinary() const {
+  assert(token_tag_ == CBORTokenTag::BINARY);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
+}
+
+span<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
+  assert(token_tag_ == CBORTokenTag::ENVELOPE);
+  auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+  return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length);
+}
+
+void CBORTokenizer::ReadNextToken(bool enter_envelope) {
+  if (enter_envelope) {
+    status_.pos += kEncodedEnvelopeHeaderSize;
+  } else {
+    status_.pos =
+        status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_;
+  }
+  status_.error = Error::OK;
+  if (status_.pos >= bytes_.size()) {
+    token_tag_ = CBORTokenTag::DONE;
+    return;
+  }
+  switch (bytes_[status_.pos]) {
+    case kStopByte:
+      SetToken(CBORTokenTag::STOP, 1);
+      return;
+    case kInitialByteIndefiniteLengthMap:
+      SetToken(CBORTokenTag::MAP_START, 1);
+      return;
+    case kInitialByteIndefiniteLengthArray:
+      SetToken(CBORTokenTag::ARRAY_START, 1);
+      return;
+    case kEncodedTrue:
+      SetToken(CBORTokenTag::TRUE_VALUE, 1);
+      return;
+    case kEncodedFalse:
+      SetToken(CBORTokenTag::FALSE_VALUE, 1);
+      return;
+    case kEncodedNull:
+      SetToken(CBORTokenTag::NULL_VALUE, 1);
+      return;
+    case kExpectedConversionToBase64Tag: {  // BINARY
+      int8_t bytes_read = internals::ReadTokenStart(
+          bytes_.subspan(status_.pos + 1), &token_start_type_,
+          &token_start_internal_value_);
+      int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_;
+      if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
+          status_.pos + token_byte_length > bytes_.size()) {
+        SetError(Error::CBOR_INVALID_BINARY);
+        return;
+      }
+      SetToken(CBORTokenTag::BINARY,
+               static_cast<std::ptrdiff_t>(token_byte_length));
+      return;
+    }
+    case kInitialByteForDouble: {  // DOUBLE
+      if (status_.pos + kEncodedDoubleSize > bytes_.size()) {
+        SetError(Error::CBOR_INVALID_DOUBLE);
+        return;
+      }
+      SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize);
+      return;
+    }
+    case kInitialByteForEnvelope: {  // ENVELOPE
+      if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) {
+        SetError(Error::CBOR_INVALID_ENVELOPE);
+        return;
+      }
+      // The envelope must be a byte string with 32 bit length.
+      if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) {
+        SetError(Error::CBOR_INVALID_ENVELOPE);
+        return;
+      }
+      // Read the length of the byte string.
+      token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
+          bytes_.subspan(status_.pos + 2));
+      // Make sure the payload is contained within the message.
+      if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize +
+              status_.pos >
+          static_cast<std::size_t>(bytes_.size())) {
+        SetError(Error::CBOR_INVALID_ENVELOPE);
+        return;
+      }
+      auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
+      SetToken(CBORTokenTag::ENVELOPE, kEncodedEnvelopeHeaderSize + length);
+      return;
+    }
+    default: {
+      span<uint8_t> remainder =
+          bytes_.subspan(status_.pos, bytes_.size() - status_.pos);
+      assert(!remainder.empty());
+      int8_t token_start_length = internals::ReadTokenStart(
+          remainder, &token_start_type_, &token_start_internal_value_);
+      bool success = token_start_length != -1;
+      switch (token_start_type_) {
+        case MajorType::UNSIGNED:  // INT32.
+          if (!success || std::numeric_limits<int32_t>::max() <
+                              token_start_internal_value_) {
+            SetError(Error::CBOR_INVALID_INT32);
+            return;
+          }
+          SetToken(CBORTokenTag::INT32, token_start_length);
+          return;
+        case MajorType::NEGATIVE:  // INT32.
+          if (!success ||
+              std::numeric_limits<int32_t>::min() >
+                  -static_cast<int64_t>(token_start_internal_value_) - 1) {
+            SetError(Error::CBOR_INVALID_INT32);
+            return;
+          }
+          SetToken(CBORTokenTag::INT32, token_start_length);
+          return;
+        case MajorType::STRING: {  // STRING8.
+          if (!success || remainder.size() < static_cast<int64_t>(
+                                                 token_start_internal_value_)) {
+            SetError(Error::CBOR_INVALID_STRING8);
+            return;
+          }
+          auto length =
+              static_cast<std::ptrdiff_t>(token_start_internal_value_);
+          SetToken(CBORTokenTag::STRING8, token_start_length + length);
+          return;
+        }
+        case MajorType::BYTE_STRING: {  // STRING16.
+          if (!success ||
+              remainder.size() <
+                  static_cast<int64_t>(token_start_internal_value_) ||
+              // Must be divisible by 2 since UTF16 is 2 bytes per character.
+              token_start_internal_value_ & 1) {
+            SetError(Error::CBOR_INVALID_STRING16);
+            return;
+          }
+          auto length =
+              static_cast<std::ptrdiff_t>(token_start_internal_value_);
+          SetToken(CBORTokenTag::STRING16, token_start_length + length);
+          return;
+        }
+        case MajorType::ARRAY:
+        case MajorType::MAP:
+        case MajorType::TAG:
+        case MajorType::SIMPLE_VALUE:
+          SetError(Error::CBOR_UNSUPPORTED_VALUE);
+          return;
+      }
+    }
+  }
+}
+
+void CBORTokenizer::SetToken(CBORTokenTag token_tag,
+                             std::ptrdiff_t token_byte_length) {
+  token_tag_ = token_tag;
+  token_byte_length_ = token_byte_length;
+}
+
+void CBORTokenizer::SetError(Error error) {
+  token_tag_ = CBORTokenTag::ERROR_VALUE;
+  status_.error = error;
+}
+
+// =============================================================================
+// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
+// =============================================================================
+
+namespace {
+// When parsing CBOR, we limit recursion depth for objects and arrays
+// to this constant.
+static constexpr int kStackLimit = 1000;
+
+// Below are three parsing routines for CBOR, which cover enough
+// to roundtrip JSON messages.
+bool ParseMap(int32_t stack_depth,
+              CBORTokenizer* tokenizer,
+              StreamingParserHandler* out);
+bool ParseArray(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out);
+bool ParseValue(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out);
+
+void ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
+  std::vector<uint16_t> value;
+  span<uint8_t> rep = tokenizer->GetString16WireRep();
+  for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2)
+    value.push_back((rep[ii + 1] << 8) | rep[ii]);
+  out->HandleString16(span<uint16_t>(value.data(), value.size()));
+  tokenizer->Next();
+}
+
+bool ParseUTF8String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
+  assert(tokenizer->TokenTag() == CBORTokenTag::STRING8);
+  out->HandleString8(tokenizer->GetString8());
+  tokenizer->Next();
+  return true;
+}
+
+bool ParseValue(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out) {
+  if (stack_depth > kStackLimit) {
+    out->HandleError(
+        Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos});
+    return false;
+  }
+  // Skip past the envelope to get to what's inside.
+  if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE)
+    tokenizer->EnterEnvelope();
+  switch (tokenizer->TokenTag()) {
+    case CBORTokenTag::ERROR_VALUE:
+      out->HandleError(tokenizer->Status());
+      return false;
+    case CBORTokenTag::DONE:
+      out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
+                              tokenizer->Status().pos});
+      return false;
+    case CBORTokenTag::TRUE_VALUE:
+      out->HandleBool(true);
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::FALSE_VALUE:
+      out->HandleBool(false);
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::NULL_VALUE:
+      out->HandleNull();
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::INT32:
+      out->HandleInt32(tokenizer->GetInt32());
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::DOUBLE:
+      out->HandleDouble(tokenizer->GetDouble());
+      tokenizer->Next();
+      return true;
+    case CBORTokenTag::STRING8:
+      return ParseUTF8String(tokenizer, out);
+    case CBORTokenTag::STRING16:
+      ParseUTF16String(tokenizer, out);
+      return true;
+    case CBORTokenTag::BINARY: {
+      out->HandleBinary(tokenizer->GetBinary());
+      tokenizer->Next();
+      return true;
+    }
+    case CBORTokenTag::MAP_START:
+      return ParseMap(stack_depth + 1, tokenizer, out);
+    case CBORTokenTag::ARRAY_START:
+      return ParseArray(stack_depth + 1, tokenizer, out);
+    default:
+      out->HandleError(
+          Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos});
+      return false;
+  }
+}
+
+// |bytes| must start with the indefinite length array byte, so basically,
+// ParseArray may only be called after an indefinite length array has been
+// detected.
+bool ParseArray(int32_t stack_depth,
+                CBORTokenizer* tokenizer,
+                StreamingParserHandler* out) {
+  assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
+  tokenizer->Next();
+  out->HandleArrayBegin();
+  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
+    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
+      out->HandleError(
+          Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos});
+      return false;
+    }
+    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
+      out->HandleError(tokenizer->Status());
+      return false;
+    }
+    // Parse value.
+    if (!ParseValue(stack_depth, tokenizer, out))
+      return false;
+  }
+  out->HandleArrayEnd();
+  tokenizer->Next();
+  return true;
+}
+
+// |bytes| must start with the indefinite length array byte, so basically,
+// ParseArray may only be called after an indefinite length array has been
+// detected.
+bool ParseMap(int32_t stack_depth,
+              CBORTokenizer* tokenizer,
+              StreamingParserHandler* out) {
+  assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START);
+  out->HandleMapBegin();
+  tokenizer->Next();
+  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
+    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
+      out->HandleError(
+          Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos});
+      return false;
+    }
+    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
+      out->HandleError(tokenizer->Status());
+      return false;
+    }
+    // Parse key.
+    if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
+      if (!ParseUTF8String(tokenizer, out))
+        return false;
+    } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
+      ParseUTF16String(tokenizer, out);
+    } else {
+      out->HandleError(
+          Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos});
+      return false;
+    }
+    // Parse value.
+    if (!ParseValue(stack_depth, tokenizer, out))
+      return false;
+  }
+  out->HandleMapEnd();
+  tokenizer->Next();
+  return true;
+}
+}  // namespace
+
+void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out) {
+  if (bytes.empty()) {
+    out->HandleError(Status{Error::CBOR_NO_INPUT, 0});
+    return;
+  }
+  if (bytes[0] != kInitialByteForEnvelope) {
+    out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0});
+    return;
+  }
+  CBORTokenizer tokenizer(bytes);
+  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
+    out->HandleError(tokenizer.Status());
+    return;
+  }
+  // We checked for the envelope start byte above, so the tokenizer
+  // must agree here, since it's not an error.
+  assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE);
+  tokenizer.EnterEnvelope();
+  if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) {
+    out->HandleError(
+        Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos});
+    return;
+  }
+  if (!ParseMap(/*stack_depth=*/1, &tokenizer, out))
+    return;
+  if (tokenizer.TokenTag() == CBORTokenTag::DONE)
+    return;
+  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
+    out->HandleError(tokenizer.Status());
+    return;
+  }
+  out->HandleError(Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos});
+}
+}  // namespace cbor
+
+namespace json {
+
+// =============================================================================
+// json::NewJSONEncoder - for encoding streaming parser events as JSON
+// =============================================================================
+
+namespace {
+// Prints |value| to |out| with 4 hex digits, most significant chunk first.
+void PrintHex(uint16_t value, std::string* out) {
+  for (int ii = 3; ii >= 0; --ii) {
+    int four_bits = 0xf & (value >> (4 * ii));
+    out->append(1, four_bits + ((four_bits <= 9) ? '0' : ('a' - 10)));
+  }
+}
+
+// In the writer below, we maintain a stack of State instances.
+// It is just enough to emit the appropriate delimiters and brackets
+// in JSON.
+enum class Container {
+  // Used for the top-level, initial state.
+  NONE,
+  // Inside a JSON object.
+  MAP,
+  // Inside a JSON array.
+  ARRAY
+};
+class State {
+ public:
+  explicit State(Container container) : container_(container) {}
+  void StartElement(std::string* out) {
+    assert(container_ != Container::NONE || size_ == 0);
+    if (size_ != 0) {
+      char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':';
+      out->append(1, delim);
+    }
+    ++size_;
+  }
+  Container container() const { return container_; }
+
+ private:
+  Container container_ = Container::NONE;
+  int size_ = 0;
+};
+
+constexpr char kBase64Table[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz0123456789+/";
+
+void Base64Encode(const span<uint8_t>& in, std::string* out) {
+  // The following three cases are based on the tables in the example
+  // section in https://en.wikipedia.org/wiki/Base64. We process three
+  // input bytes at a time, emitting 4 output bytes at a time.
+  std::ptrdiff_t ii = 0;
+
+  // While possible, process three input bytes.
+  for (; ii + 3 <= in.size(); ii += 3) {
+    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2];
+    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
+    out->push_back(kBase64Table[twentyfour_bits & 0x3f]);
+  }
+  if (ii + 2 <= in.size()) {  // Process two input bytes.
+    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8);
+    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
+    out->push_back('=');  // Emit padding.
+    return;
+  }
+  if (ii + 1 <= in.size()) {  // Process a single input byte.
+    uint32_t twentyfour_bits = (in[ii] << 16);
+    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
+    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
+    out->push_back('=');  // Emit padding.
+    out->push_back('=');  // Emit padding.
+  }
+}
+
+// Implements a handler for JSON parser events to emit a JSON string.
+class JSONEncoder : public StreamingParserHandler {
+ public:
+  JSONEncoder(const Platform* platform, std::string* out, Status* status)
+      : platform_(platform), out_(out), status_(status) {
+    *status_ = Status();
+    state_.emplace(Container::NONE);
+  }
+
+  void HandleMapBegin() override {
+    if (!status_->ok())
+      return;
+    assert(!state_.empty());
+    state_.top().StartElement(out_);
+    state_.emplace(Container::MAP);
+    out_->append("{");
+  }
+
+  void HandleMapEnd() override {
+    if (!status_->ok())
+      return;
+    assert(state_.size() >= 2 && state_.top().container() == Container::MAP);
+    state_.pop();
+    out_->append("}");
+  }
+
+  void HandleArrayBegin() override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    state_.emplace(Container::ARRAY);
+    out_->append("[");
+  }
+
+  void HandleArrayEnd() override {
+    if (!status_->ok())
+      return;
+    assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY);
+    state_.pop();
+    out_->append("]");
+  }
+
+  void HandleString16(span<uint16_t> chars) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("\"");
+    for (const uint16_t ch : chars) {
+      if (ch == '"') {
+        out_->append("\\\"");
+      } else if (ch == '\\') {
+        out_->append("\\\\");
+      } else if (ch == '\b') {
+        out_->append("\\b");
+      } else if (ch == '\f') {
+        out_->append("\\f");
+      } else if (ch == '\n') {
+        out_->append("\\n");
+      } else if (ch == '\r') {
+        out_->append("\\r");
+      } else if (ch == '\t') {
+        out_->append("\\t");
+      } else if (ch >= 32 && ch <= 126) {
+        out_->append(1, ch);
+      } else {
+        out_->append("\\u");
+        PrintHex(ch, out_);
+      }
+    }
+    out_->append("\"");
+  }
+
+  void HandleString8(span<uint8_t> chars) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("\"");
+    for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) {
+      uint8_t c = chars[ii];
+      if (c == '"') {
+        out_->append("\\\"");
+      } else if (c == '\\') {
+        out_->append("\\\\");
+      } else if (c == '\b') {
+        out_->append("\\b");
+      } else if (c == '\f') {
+        out_->append("\\f");
+      } else if (c == '\n') {
+        out_->append("\\n");
+      } else if (c == '\r') {
+        out_->append("\\r");
+      } else if (c == '\t') {
+        out_->append("\\t");
+      } else if (c >= 32 && c <= 126) {
+        out_->append(1, c);
+      } else if (c < 32) {
+        out_->append("\\u");
+        PrintHex(static_cast<uint16_t>(c), out_);
+      } else {
+        // Inspect the leading byte to figure out how long the utf8
+        // byte sequence is; while doing this initialize |codepoint|
+        // with the first few bits.
+        // See table in: https://en.wikipedia.org/wiki/UTF-8
+        // byte one is 110x xxxx -> 2 byte utf8 sequence
+        // byte one is 1110 xxxx -> 3 byte utf8 sequence
+        // byte one is 1111 0xxx -> 4 byte utf8 sequence
+        uint32_t codepoint;
+        int num_bytes_left;
+        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
+          num_bytes_left = 1;
+          codepoint = c & 0x1f;
+        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
+          num_bytes_left = 2;
+          codepoint = c & 0x0f;
+        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
+          codepoint = c & 0x07;
+          num_bytes_left = 3;
+        } else {
+          continue;  // invalid leading byte
+        }
+
+        // If we have enough bytes in our input, decode the remaining ones
+        // belonging to this Unicode character into |codepoint|.
+        if (ii + num_bytes_left > chars.size())
+          continue;
+        while (num_bytes_left > 0) {
+          c = chars[++ii];
+          --num_bytes_left;
+          // Check the next byte is a continuation byte, that is 10xx xxxx.
+          if ((c & 0xc0) != 0x80)
+            continue;
+          codepoint = (codepoint << 6) | (c & 0x3f);
+        }
+
+        // Disallow overlong encodings for ascii characters, as these
+        // would include " and other characters significant to JSON
+        // string termination / control.
+        if (codepoint < 0x7f)
+          continue;
+        // Invalid in UTF8, and can't be represented in UTF16 anyway.
+        if (codepoint > 0x10ffff)
+          continue;
+
+        // So, now we transcode to UTF16,
+        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
+        // for either one or two 16 bit characters.
+        if (codepoint < 0xffff) {
+          out_->append("\\u");
+          PrintHex(static_cast<uint16_t>(codepoint), out_);
+          continue;
+        }
+        codepoint -= 0x10000;
+        // high surrogate
+        out_->append("\\u");
+        PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_);
+        // low surrogate
+        out_->append("\\u");
+        PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_);
+      }
+    }
+    out_->append("\"");
+  }
+
+  void HandleBinary(span<uint8_t> bytes) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("\"");
+    Base64Encode(bytes, out_);
+    out_->append("\"");
+  }
+
+  void HandleDouble(double value) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    std::unique_ptr<char[]> str_value = platform_->DToStr(value);
+
+    // DToStr may fail to emit a 0 before the decimal dot. E.g. this is
+    // the case in base::NumberToString in Chromium (which is based on
+    // dmg_fp). So, much like
+    // https://cs.chromium.org/chromium/src/base/json/json_writer.cc
+    // we probe for this and emit the leading 0 anyway if necessary.
+    const char* chars = str_value.get();
+    if (chars[0] == '.') {
+      out_->append("0");
+    } else if (chars[0] == '-' && chars[1] == '.') {
+      out_->append("-0");
+      ++chars;
+    }
+    out_->append(chars);
+  }
+
+  void HandleInt32(int32_t value) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append(std::to_string(value));
+  }
+
+  void HandleBool(bool value) override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append(value ? "true" : "false");
+  }
+
+  void HandleNull() override {
+    if (!status_->ok())
+      return;
+    state_.top().StartElement(out_);
+    out_->append("null");
+  }
+
+  void HandleError(Status error) override {
+    assert(!error.ok());
+    *status_ = error;
+    out_->clear();
+  }
+
+ private:
+  const Platform* platform_;
+  std::string* out_;
+  Status* status_;
+  std::stack<State> state_;
+};
+}  // namespace
+
+std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform,
+                                                       std::string* out,
+                                                       Status* status) {
+  return std::unique_ptr<StreamingParserHandler>(
+      new JSONEncoder(platform, out, status));
+}
+
+// =============================================================================
+// json::ParseJSON - for receiving streaming parser events for JSON.
+// =============================================================================
+
+namespace {
+const int kStackLimit = 1000;
+
+enum Token {
+  ObjectBegin,
+  ObjectEnd,
+  ArrayBegin,
+  ArrayEnd,
+  StringLiteral,
+  Number,
+  BoolTrue,
+  BoolFalse,
+  NullToken,
+  ListSeparator,
+  ObjectPairSeparator,
+  InvalidToken,
+  NoInput
+};
+
+const char* const kNullString = "null";
+const char* const kTrueString = "true";
+const char* const kFalseString = "false";
+
+template <typename Char>
+class JsonParser {
+ public:
+  JsonParser(const Platform* platform, StreamingParserHandler* handler)
+      : platform_(platform), handler_(handler) {}
+
+  void Parse(const Char* start, std::size_t length) {
+    start_pos_ = start;
+    const Char* end = start + length;
+    const Char* tokenEnd;
+    ParseValue(start, end, &tokenEnd, 0);
+    if (tokenEnd != end) {
+      HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd);
+    }
+  }
+
+ private:
+  bool CharsToDouble(const uint16_t* chars,
+                     std::size_t length,
+                     double* result) {
+    std::string buffer;
+    buffer.reserve(length + 1);
+    for (std::size_t ii = 0; ii < length; ++ii) {
+      bool is_ascii = !(chars[ii] & ~0x7F);
+      if (!is_ascii)
+        return false;
+      buffer.push_back(static_cast<char>(chars[ii]));
+    }
+    return platform_->StrToD(buffer.c_str(), result);
+  }
+
+  bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) {
+    std::string buffer(reinterpret_cast<const char*>(chars), length);
+    return platform_->StrToD(buffer.c_str(), result);
+  }
+
+  static bool ParseConstToken(const Char* start,
+                              const Char* end,
+                              const Char** token_end,
+                              const char* token) {
+    // |token| is \0 terminated, it's one of the constants at top of the file.
+    while (start < end && *token != '\0' && *start++ == *token++) {
+    }
+    if (*token != '\0')
+      return false;
+    *token_end = start;
+    return true;
+  }
+
+  static bool ReadInt(const Char* start,
+                      const Char* end,
+                      const Char** token_end,
+                      bool allow_leading_zeros) {
+    if (start == end)
+      return false;
+    bool has_leading_zero = '0' == *start;
+    int length = 0;
+    while (start < end && '0' <= *start && *start <= '9') {
+      ++start;
+      ++length;
+    }
+    if (!length)
+      return false;
+    if (!allow_leading_zeros && length > 1 && has_leading_zero)
+      return false;
+    *token_end = start;
+    return true;
+  }
+
+  static bool ParseNumberToken(const Char* start,
+                               const Char* end,
+                               const Char** token_end) {
+    // We just grab the number here. We validate the size in DecodeNumber.
+    // According to RFC4627, a valid number is: [minus] int [frac] [exp]
+    if (start == end)
+      return false;
+    Char c = *start;
+    if ('-' == c)
+      ++start;
+
+    if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false))
+      return false;
+    if (start == end) {
+      *token_end = start;
+      return true;
+    }
+
+    // Optional fraction part
+    c = *start;
+    if ('.' == c) {
+      ++start;
+      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
+        return false;
+      if (start == end) {
+        *token_end = start;
+        return true;
+      }
+      c = *start;
+    }
+
+    // Optional exponent part
+    if ('e' == c || 'E' == c) {
+      ++start;
+      if (start == end)
+        return false;
+      c = *start;
+      if ('-' == c || '+' == c) {
+        ++start;
+        if (start == end)
+          return false;
+      }
+      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
+        return false;
+    }
+
+    *token_end = start;
+    return true;
+  }
+
+  static bool ReadHexDigits(const Char* start,
+                            const Char* end,
+                            const Char** token_end,
+                            int digits) {
+    if (end - start < digits)
+      return false;
+    for (int i = 0; i < digits; ++i) {
+      Char c = *start++;
+      if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
+            ('A' <= c && c <= 'F')))
+        return false;
+    }
+    *token_end = start;
+    return true;
+  }
+
+  static bool ParseStringToken(const Char* start,
+                               const Char* end,
+                               const Char** token_end) {
+    while (start < end) {
+      Char c = *start++;
+      if ('\\' == c) {
+        if (start == end)
+          return false;
+        c = *start++;
+        // Make sure the escaped char is valid.
+        switch (c) {
+          case 'x':
+            if (!ReadHexDigits(start, end, &start, 2))
+              return false;
+            break;
+          case 'u':
+            if (!ReadHexDigits(start, end, &start, 4))
+              return false;
+            break;
+          case '\\':
+          case '/':
+          case 'b':
+          case 'f':
+          case 'n':
+          case 'r':
+          case 't':
+          case 'v':
+          case '"':
+            break;
+          default:
+            return false;
+        }
+      } else if ('"' == c) {
+        *token_end = start;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static bool SkipComment(const Char* start,
+                          const Char* end,
+                          const Char** comment_end) {
+    if (start == end)
+      return false;
+
+    if (*start != '/' || start + 1 >= end)
+      return false;
+    ++start;
+
+    if (*start == '/') {
+      // Single line comment, read to newline.
+      for (++start; start < end; ++start) {
+        if (*start == '\n' || *start == '\r') {
+          *comment_end = start + 1;
+          return true;
+        }
+      }
+      *comment_end = end;
+      // Comment reaches end-of-input, which is fine.
+      return true;
+    }
+
+    if (*start == '*') {
+      Char previous = '\0';
+      // Block comment, read until end marker.
+      for (++start; start < end; previous = *start++) {
+        if (previous == '*' && *start == '/') {
+          *comment_end = start + 1;
+          return true;
+        }
+      }
+      // Block comment must close before end-of-input.
+      return false;
+    }
+
+    return false;
+  }
+
+  static bool IsSpaceOrNewLine(Char c) {
+    // \v = vertial tab; \f = form feed page break.
+    return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' ||
+           c == '\t';
+  }
+
+  static void SkipWhitespaceAndComments(const Char* start,
+                                        const Char* end,
+                                        const Char** whitespace_end) {
+    while (start < end) {
+      if (IsSpaceOrNewLine(*start)) {
+        ++start;
+      } else if (*start == '/') {
+        const Char* comment_end;
+        if (!SkipComment(start, end, &comment_end))
+          break;
+        start = comment_end;
+      } else {
+        break;
+      }
+    }
+    *whitespace_end = start;
+  }
+
+  static Token ParseToken(const Char* start,
+                          const Char* end,
+                          const Char** tokenStart,
+                          const Char** token_end) {
+    SkipWhitespaceAndComments(start, end, tokenStart);
+    start = *tokenStart;
+
+    if (start == end)
+      return NoInput;
+
+    switch (*start) {
+      case 'n':
+        if (ParseConstToken(start, end, token_end, kNullString))
+          return NullToken;
+        break;
+      case 't':
+        if (ParseConstToken(start, end, token_end, kTrueString))
+          return BoolTrue;
+        break;
+      case 'f':
+        if (ParseConstToken(start, end, token_end, kFalseString))
+          return BoolFalse;
+        break;
+      case '[':
+        *token_end = start + 1;
+        return ArrayBegin;
+      case ']':
+        *token_end = start + 1;
+        return ArrayEnd;
+      case ',':
+        *token_end = start + 1;
+        return ListSeparator;
+      case '{':
+        *token_end = start + 1;
+        return ObjectBegin;
+      case '}':
+        *token_end = start + 1;
+        return ObjectEnd;
+      case ':':
+        *token_end = start + 1;
+        return ObjectPairSeparator;
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+      case '-':
+        if (ParseNumberToken(start, end, token_end))
+          return Number;
+        break;
+      case '"':
+        if (ParseStringToken(start + 1, end, token_end))
+          return StringLiteral;
+        break;
+    }
+    return InvalidToken;
+  }
+
+  static int HexToInt(Char c) {
+    if ('0' <= c && c <= '9')
+      return c - '0';
+    if ('A' <= c && c <= 'F')
+      return c - 'A' + 10;
+    if ('a' <= c && c <= 'f')
+      return c - 'a' + 10;
+    assert(false);  // Unreachable.
+    return 0;
+  }
+
+  static bool DecodeString(const Char* start,
+                           const Char* end,
+                           std::vector<uint16_t>* output) {
+    if (start == end)
+      return true;
+    if (start > end)
+      return false;
+    output->reserve(end - start);
+    while (start < end) {
+      uint16_t c = *start++;
+      // If the |Char| we're dealing with is really a byte, then
+      // we have utf8 here, and we need to check for multibyte characters
+      // and transcode them to utf16 (either one or two utf16 chars).
+      if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) {
+        // Inspect the leading byte to figure out how long the utf8
+        // byte sequence is; while doing this initialize |codepoint|
+        // with the first few bits.
+        // See table in: https://en.wikipedia.org/wiki/UTF-8
+        // byte one is 110x xxxx -> 2 byte utf8 sequence
+        // byte one is 1110 xxxx -> 3 byte utf8 sequence
+        // byte one is 1111 0xxx -> 4 byte utf8 sequence
+        uint32_t codepoint;
+        int num_bytes_left;
+        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
+          num_bytes_left = 1;
+          codepoint = c & 0x1f;
+        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
+          num_bytes_left = 2;
+          codepoint = c & 0x0f;
+        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
+          codepoint = c & 0x07;
+          num_bytes_left = 3;
+        } else {
+          return false;  // invalid leading byte
+        }
+
+        // If we have enough bytes in our inpput, decode the remaining ones
+        // belonging to this Unicode character into |codepoint|.
+        if (start + num_bytes_left > end)
+          return false;
+        while (num_bytes_left > 0) {
+          c = *start++;
+          --num_bytes_left;
+          // Check the next byte is a continuation byte, that is 10xx xxxx.
+          if ((c & 0xc0) != 0x80)
+            return false;
+          codepoint = (codepoint << 6) | (c & 0x3f);
+        }
+
+        // Disallow overlong encodings for ascii characters, as these
+        // would include " and other characters significant to JSON
+        // string termination / control.
+        if (codepoint < 0x7f)
+          return false;
+        // Invalid in UTF8, and can't be represented in UTF16 anyway.
+        if (codepoint > 0x10ffff)
+          return false;
+
+        // So, now we transcode to UTF16,
+        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
+        // for either one or two 16 bit characters.
+        if (codepoint < 0xffff) {
+          output->push_back(codepoint);
+          continue;
+        }
+        codepoint -= 0x10000;
+        output->push_back((codepoint >> 10) + 0xd800);    // high surrogate
+        output->push_back((codepoint & 0x3ff) + 0xdc00);  // low surrogate
+        continue;
+      }
+      if ('\\' != c) {
+        output->push_back(c);
+        continue;
+      }
+      if (start == end)
+        return false;
+      c = *start++;
+
+      if (c == 'x') {
+        // \x is not supported.
+        return false;
+      }
+
+      switch (c) {
+        case '"':
+        case '/':
+        case '\\':
+          break;
+        case 'b':
+          c = '\b';
+          break;
+        case 'f':
+          c = '\f';
+          break;
+        case 'n':
+          c = '\n';
+          break;
+        case 'r':
+          c = '\r';
+          break;
+        case 't':
+          c = '\t';
+          break;
+        case 'v':
+          c = '\v';
+          break;
+        case 'u':
+          c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) +
+              (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3));
+          start += 4;
+          break;
+        default:
+          return false;
+      }
+      output->push_back(c);
+    }
+    return true;
+  }
+
+  void ParseValue(const Char* start,
+                  const Char* end,
+                  const Char** value_token_end,
+                  int depth) {
+    if (depth > kStackLimit) {
+      HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start);
+      return;
+    }
+    const Char* token_start;
+    const Char* token_end;
+    Token token = ParseToken(start, end, &token_start, &token_end);
+    switch (token) {
+      case NoInput:
+        HandleError(Error::JSON_PARSER_NO_INPUT, token_start);
+        return;
+      case InvalidToken:
+        HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start);
+        return;
+      case NullToken:
+        handler_->HandleNull();
+        break;
+      case BoolTrue:
+        handler_->HandleBool(true);
+        break;
+      case BoolFalse:
+        handler_->HandleBool(false);
+        break;
+      case Number: {
+        double value;
+        if (!CharsToDouble(token_start, token_end - token_start, &value)) {
+          HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start);
+          return;
+        }
+        if (value >= std::numeric_limits<int32_t>::min() &&
+            value <= std::numeric_limits<int32_t>::max() &&
+            static_cast<int32_t>(value) == value)
+          handler_->HandleInt32(static_cast<int32_t>(value));
+        else
+          handler_->HandleDouble(value);
+        break;
+      }
+      case StringLiteral: {
+        std::vector<uint16_t> value;
+        bool ok = DecodeString(token_start + 1, token_end - 1, &value);
+        if (!ok) {
+          HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
+          return;
+        }
+        handler_->HandleString16(span<uint16_t>(value.data(), value.size()));
+        break;
+      }
+      case ArrayBegin: {
+        handler_->HandleArrayBegin();
+        start = token_end;
+        token = ParseToken(start, end, &token_start, &token_end);
+        while (token != ArrayEnd) {
+          ParseValue(start, end, &token_end, depth + 1);
+          if (error_)
+            return;
+
+          // After a list value, we expect a comma or the end of the list.
+          start = token_end;
+          token = ParseToken(start, end, &token_start, &token_end);
+          if (token == ListSeparator) {
+            start = token_end;
+            token = ParseToken(start, end, &token_start, &token_end);
+            if (token == ArrayEnd) {
+              HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start);
+              return;
+            }
+          } else if (token != ArrayEnd) {
+            // Unexpected value after list value. Bail out.
+            HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
+                        token_start);
+            return;
+          }
+        }
+        handler_->HandleArrayEnd();
+        break;
+      }
+      case ObjectBegin: {
+        handler_->HandleMapBegin();
+        start = token_end;
+        token = ParseToken(start, end, &token_start, &token_end);
+        while (token != ObjectEnd) {
+          if (token != StringLiteral) {
+            HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED,
+                        token_start);
+            return;
+          }
+          std::vector<uint16_t> key;
+          if (!DecodeString(token_start + 1, token_end - 1, &key)) {
+            HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
+            return;
+          }
+          handler_->HandleString16(span<uint16_t>(key.data(), key.size()));
+          start = token_end;
+
+          token = ParseToken(start, end, &token_start, &token_end);
+          if (token != ObjectPairSeparator) {
+            HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start);
+            return;
+          }
+          start = token_end;
+
+          ParseValue(start, end, &token_end, depth + 1);
+          if (error_)
+            return;
+          start = token_end;
+
+          // After a key/value pair, we expect a comma or the end of the
+          // object.
+          token = ParseToken(start, end, &token_start, &token_end);
+          if (token == ListSeparator) {
+            start = token_end;
+            token = ParseToken(start, end, &token_start, &token_end);
+            if (token == ObjectEnd) {
+              HandleError(Error::JSON_PARSER_UNEXPECTED_MAP_END, token_start);
+              return;
+            }
+          } else if (token != ObjectEnd) {
+            // Unexpected value after last object value. Bail out.
+            HandleError(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED,
+                        token_start);
+            return;
+          }
+        }
+        handler_->HandleMapEnd();
+        break;
+      }
+
+      default:
+        // We got a token that's not a value.
+        HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start);
+        return;
+    }
+
+    SkipWhitespaceAndComments(token_end, end, value_token_end);
+  }
+
+  void HandleError(Error error, const Char* pos) {
+    assert(error != Error::OK);
+    if (!error_) {
+      handler_->HandleError(Status{error, pos - start_pos_});
+      error_ = true;
+    }
+  }
+
+  const Char* start_pos_ = nullptr;
+  bool error_ = false;
+  const Platform* platform_;
+  StreamingParserHandler* handler_;
+};
+}  // namespace
+
+void ParseJSON(const Platform* platform,
+               span<uint8_t> chars,
+               StreamingParserHandler* handler) {
+  JsonParser<uint8_t> parser(platform, handler);
+  parser.Parse(chars.data(), chars.size());
+}
+
+void ParseJSON(const Platform* platform,
+               span<uint16_t> chars,
+               StreamingParserHandler* handler) {
+  JsonParser<uint16_t> parser(platform, handler);
+  parser.Parse(chars.data(), chars.size());
+}
+}  // namespace json
+
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
+
diff --git a/third_party/inspector_protocol/lib/CBOR_h.template b/third_party/inspector_protocol/lib/encoding_h.template
similarity index 65%
copy from third_party/inspector_protocol/lib/CBOR_h.template
copy to third_party/inspector_protocol/lib/encoding_h.template
index 9d28adb..aba28c8 100644
--- a/third_party/inspector_protocol/lib/CBOR_h.template
+++ b/third_party/inspector_protocol/lib/encoding_h.template
@@ -1,75 +1,29 @@
 {# This template is generated by gen_cbor_templates.py. #}
-// Generated by lib/CBOR_h.template.
+// Generated by lib/encoding_h.template.
 
 // Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef {{"_".join(config.protocol.namespace)}}_CBOR_h
-#define {{"_".join(config.protocol.namespace)}}_CBOR_h
+#ifndef {{"_".join(config.protocol.namespace)}}_encoding_h
+#define {{"_".join(config.protocol.namespace)}}_encoding_h
 
 #include <cstddef>
 #include <cstdint>
 #include <memory>
+#include <string>
 #include <vector>
 
 {% for namespace in config.protocol.namespace %}
 namespace {{namespace}} {
 {% endfor %}
 
-// ===== encoding/status.h =====
+// ===== encoding/encoding.h =====
 
-// Error codes.
-enum class Error {
-  OK = 0,
-  // JSON parsing errors - json_parser.{h,cc}.
-  JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
-  JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
-  JSON_PARSER_NO_INPUT = 0x03,
-  JSON_PARSER_INVALID_TOKEN = 0x04,
-  JSON_PARSER_INVALID_NUMBER = 0x05,
-  JSON_PARSER_INVALID_STRING = 0x06,
-  JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07,
-  JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08,
-  JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09,
-  JSON_PARSER_COLON_EXPECTED = 0x0a,
-  JSON_PARSER_UNEXPECTED_OBJECT_END = 0x0b,
-  JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED = 0x0c,
-  JSON_PARSER_VALUE_EXPECTED = 0x0d,
 
-  CBOR_INVALID_INT32 = 0x0e,
-  CBOR_INVALID_DOUBLE = 0x0f,
-  CBOR_INVALID_ENVELOPE = 0x10,
-  CBOR_INVALID_STRING8 = 0x11,
-  CBOR_INVALID_STRING16 = 0x12,
-  CBOR_INVALID_BINARY = 0x13,
-  CBOR_UNSUPPORTED_VALUE = 0x14,
-  CBOR_NO_INPUT = 0x15,
-  CBOR_INVALID_START_BYTE = 0x16,
-  CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17,
-  CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18,
-  CBOR_UNEXPECTED_EOF_IN_MAP = 0x19,
-  CBOR_INVALID_MAP_KEY = 0x1a,
-  CBOR_STACK_LIMIT_EXCEEDED = 0x1b,
-  CBOR_STRING8_MUST_BE_7BIT = 0x1c,
-  CBOR_TRAILING_JUNK = 0x1d,
-  CBOR_MAP_START_EXPECTED = 0x1e,
-};
-
-// A status value with position that can be copied. The default status
-// is OK. Usually, error status values should come with a valid position.
-struct Status {
-  static constexpr std::ptrdiff_t npos() { return -1; }
-
-  bool ok() const { return error == Error::OK; }
-
-  Error error = Error::OK;
-  std::ptrdiff_t pos = npos();
-  Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
-  Status() = default;
-};
-
-// ===== encoding/span.h =====
+// =============================================================================
+// span - sequence of bytes
+// =============================================================================
 
 // This template is similar to std::span, which will be included in C++20.  Like
 // std::span it uses ptrdiff_t, which is signed (and thus a bit annoying
@@ -107,19 +61,78 @@
   index_type size_;
 };
 
-// ===== encoding/json_parser_handler.h =====
+template <typename T>
+span<T> SpanFromVector(const std::vector<T>& v) {
+  return span<T>(v.data(), v.size());
+}
 
-// Handler interface for JSON parser events. See also json_parser.h.
-class JSONParserHandler {
+inline span<uint8_t> SpanFromStdString(const std::string& v) {
+  return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size());
+}
+
+// Error codes.
+enum class Error {
+  OK = 0,
+  // JSON parsing errors - json_parser.{h,cc}.
+  JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
+  JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
+  JSON_PARSER_NO_INPUT = 0x03,
+  JSON_PARSER_INVALID_TOKEN = 0x04,
+  JSON_PARSER_INVALID_NUMBER = 0x05,
+  JSON_PARSER_INVALID_STRING = 0x06,
+  JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07,
+  JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08,
+  JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09,
+  JSON_PARSER_COLON_EXPECTED = 0x0a,
+  JSON_PARSER_UNEXPECTED_MAP_END = 0x0b,
+  JSON_PARSER_COMMA_OR_MAP_END_EXPECTED = 0x0c,
+  JSON_PARSER_VALUE_EXPECTED = 0x0d,
+
+  CBOR_INVALID_INT32 = 0x0e,
+  CBOR_INVALID_DOUBLE = 0x0f,
+  CBOR_INVALID_ENVELOPE = 0x10,
+  CBOR_INVALID_STRING8 = 0x11,
+  CBOR_INVALID_STRING16 = 0x12,
+  CBOR_INVALID_BINARY = 0x13,
+  CBOR_UNSUPPORTED_VALUE = 0x14,
+  CBOR_NO_INPUT = 0x15,
+  CBOR_INVALID_START_BYTE = 0x16,
+  CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17,
+  CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18,
+  CBOR_UNEXPECTED_EOF_IN_MAP = 0x19,
+  CBOR_INVALID_MAP_KEY = 0x1a,
+  CBOR_STACK_LIMIT_EXCEEDED = 0x1b,
+  CBOR_STRING8_MUST_BE_7BIT = 0x1c,
+  CBOR_TRAILING_JUNK = 0x1d,
+  CBOR_MAP_START_EXPECTED = 0x1e,
+};
+
+// A status value with position that can be copied. The default status
+// is OK. Usually, error status values should come with a valid position.
+struct Status {
+  static constexpr std::ptrdiff_t npos() { return -1; }
+
+  bool ok() const { return error == Error::OK; }
+
+  Error error = Error::OK;
+  std::ptrdiff_t pos = npos();
+  Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
+  Status() = default;
+};
+
+// Handler interface for parser events emitted by a streaming parser.
+// See cbor::NewCBOREncoder, cbor::ParseCBOR, json::NewJSONEncoder,
+// json::ParseJSON.
+class StreamingParserHandler {
  public:
-  virtual ~JSONParserHandler() = default;
-  virtual void HandleObjectBegin() = 0;
-  virtual void HandleObjectEnd() = 0;
+  virtual ~StreamingParserHandler() = default;
+  virtual void HandleMapBegin() = 0;
+  virtual void HandleMapEnd() = 0;
   virtual void HandleArrayBegin() = 0;
   virtual void HandleArrayEnd() = 0;
   virtual void HandleString8(span<uint8_t> chars) = 0;
   virtual void HandleString16(span<uint16_t> chars) = 0;
-  virtual void HandleBinary(std::vector<uint8_t> bytes) = 0;
+  virtual void HandleBinary(span<uint8_t> bytes) = 0;
   virtual void HandleDouble(double value) = 0;
   virtual void HandleInt32(int32_t value) = 0;
   virtual void HandleBool(bool value) = 0;
@@ -132,97 +145,7 @@
   virtual void HandleError(Status error) = 0;
 };
 
-// ===== encoding/cbor_internals.h =====
-
 namespace cbor {
-enum class MajorType;
-}
-
-namespace cbor_internals {
-
-// Reads the start of a token with definitive size from |bytes|.
-// |type| is the major type as specified in RFC 7049 Section 2.1.
-// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
-// (e.g. for BYTE_STRING).
-// If successful, returns the number of bytes read. Otherwise returns -1.
-int8_t ReadTokenStart(span<uint8_t> bytes, cbor::MajorType* type,
-                      uint64_t* value);
-
-// Writes the start of a token with |type|. The |value| may indicate the size,
-// or it may be the payload if the value is an unsigned integer.
-void WriteTokenStart(cbor::MajorType type, uint64_t value,
-                     std::vector<uint8_t>* encoded);
-}  // namespace cbor_internals
-
-// ===== encoding/cbor.h =====
-
-
-namespace cbor {
-
-// The major types from RFC 7049 Section 2.1.
-enum class MajorType {
-  UNSIGNED = 0,
-  NEGATIVE = 1,
-  BYTE_STRING = 2,
-  STRING = 3,
-  ARRAY = 4,
-  MAP = 5,
-  TAG = 6,
-  SIMPLE_VALUE = 7
-};
-
-// Indicates the number of bits the "initial byte" needs to be shifted to the
-// right after applying |kMajorTypeMask| to produce the major type in the
-// lowermost bits.
-static constexpr uint8_t kMajorTypeBitShift = 5u;
-// Mask selecting the low-order 5 bits of the "initial byte", which is where
-// the additional information is encoded.
-static constexpr uint8_t kAdditionalInformationMask = 0x1f;
-// Mask selecting the high-order 3 bits of the "initial byte", which indicates
-// the major type of the encoded value.
-static constexpr uint8_t kMajorTypeMask = 0xe0;
-// Indicates the integer is in the following byte.
-static constexpr uint8_t kAdditionalInformation1Byte = 24u;
-// Indicates the integer is in the next 2 bytes.
-static constexpr uint8_t kAdditionalInformation2Bytes = 25u;
-// Indicates the integer is in the next 4 bytes.
-static constexpr uint8_t kAdditionalInformation4Bytes = 26u;
-// Indicates the integer is in the next 8 bytes.
-static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
-
-// Encodes the initial byte, consisting of the |type| in the first 3 bits
-// followed by 5 bits of |additional_info|.
-constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
-  return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
-         (additional_info & kAdditionalInformationMask);
-}
-
-// TAG 24 indicates that what follows is a byte string which is
-// encoded in CBOR format. We use this as a wrapper for
-// maps and arrays, allowing us to skip them, because the
-// byte string carries its size (byte length).
-// https://tools.ietf.org/html/rfc7049#section-2.4.4.1
-static constexpr uint8_t kInitialByteForEnvelope =
-    EncodeInitialByte(MajorType::TAG, 24);
-// The initial byte for a byte string with at most 2^32 bytes
-// of payload. This is used for envelope encoding, even if
-// the byte string is shorter.
-static constexpr uint8_t kInitialByteFor32BitLengthByteString =
-    EncodeInitialByte(MajorType::BYTE_STRING, 26);
-
-// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
-// info = 31.
-static constexpr uint8_t kInitialByteIndefiniteLengthArray =
-    EncodeInitialByte(MajorType::ARRAY, 31);
-static constexpr uint8_t kInitialByteIndefiniteLengthMap =
-    EncodeInitialByte(MajorType::MAP, 31);
-// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
-// length maps / arrays.
-static constexpr uint8_t kStopByte =
-    EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
-
-}  // namespace cbor
-
 // The binary encoding for the inspector protocol follows the CBOR specification
 // (RFC 7049). Additional constraints:
 // - Only indefinite length maps and arrays are supported.
@@ -239,12 +162,38 @@
 //   as CBOR BYTE_STRING (major type 2). For such strings, the number of
 //   bytes encoded must be even.
 // - UTF8 strings (major type 3) are supported.
-// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not
+// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, never
 //   as UTF16 strings.
 // - Arbitrary byte arrays, in the inspector protocol called 'binary',
 //   are encoded as BYTE_STRING (major type 2), prefixed with a byte
 //   indicating base64 when rendered as JSON.
 
+// =============================================================================
+// Detecting CBOR content
+// =============================================================================
+
+// The first byte for an envelope, which we use for wrapping dictionaries
+// and arrays; and the byte that indicates a byte string with 32 bit length.
+// These two bytes start an envelope, and thereby also any CBOR message
+// produced or consumed by this protocol. See also |EnvelopeEncoder| below.
+uint8_t InitialByteForEnvelope();
+uint8_t InitialByteFor32BitLengthByteString();
+
+// Checks whether |msg| is a cbor message.
+bool IsCBORMessage(span<uint8_t> msg);
+
+// =============================================================================
+// Encoding individual CBOR items
+// =============================================================================
+
+// Some constants for CBOR tokens that only take a single byte on the wire.
+uint8_t EncodeTrue();
+uint8_t EncodeFalse();
+uint8_t EncodeNull();
+uint8_t EncodeIndefiniteLengthArrayStart();
+uint8_t EncodeIndefiniteLengthMapStart();
+uint8_t EncodeStop();
+
 // Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE|
 // (major type 1) iff < 0.
 void EncodeInt32(int32_t value, std::vector<uint8_t>* out);
@@ -275,13 +224,9 @@
 // with additional info = 27, followed by 8 bytes in big endian.
 void EncodeDouble(double value, std::vector<uint8_t>* out);
 
-// Some constants for CBOR tokens that only take a single byte on the wire.
-uint8_t EncodeTrue();
-uint8_t EncodeFalse();
-uint8_t EncodeNull();
-uint8_t EncodeIndefiniteLengthArrayStart();
-uint8_t EncodeIndefiniteLengthMapStart();
-uint8_t EncodeStop();
+// =============================================================================
+// cbor::EnvelopeEncoder - for wrapping submessages
+// =============================================================================
 
 // An envelope indicates the byte length of a wrapped item.
 // We use this for maps and array, which allows the decoder
@@ -304,20 +249,23 @@
   std::size_t byte_size_pos_ = 0;
 };
 
-// This can be used to convert from JSON to CBOR, by passing the
-// return value to the routines in json_parser.h.  The handler will encode into
-// |out|, and iff an error occurs it will set |status| to an error and clear
-// |out|. Otherwise, |status.ok()| will be |true|.
-std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder(
-    std::vector<uint8_t>* out, Status* status);
+// =============================================================================
+// cbor::NewCBOREncoder - for encoding from a streaming parser
+// =============================================================================
 
-// Parses a CBOR encoded message from |bytes|, sending JSON events to
-// |json_out|. If an error occurs, sends |out->HandleError|, and parsing stops.
-// The client is responsible for discarding the already received information in
-// that case.
-void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out);
+// This can be used to convert to CBOR, by passing the return value to a parser
+// that drives it. The handler will encode into |out|, and iff an error occurs
+// it will set |status| to an error and clear |out|. Otherwise, |status.ok()|
+// will be |true|.
+std::unique_ptr<StreamingParserHandler> NewCBOREncoder(
+    std::vector<uint8_t>* out,
+    Status* status);
 
-// Tags for the tokens within a CBOR message that CBORStream understands.
+// =============================================================================
+// cbor::CBORTokenizer - for parsing individual CBOR items
+// =============================================================================
+
+// Tags for the tokens within a CBOR message that CBORTokenizer understands.
 // Note that this is not the same terminology as the CBOR spec (RFC 7049),
 // but rather, our adaptation. For instance, we lump unsigned and signed
 // major type into INT32 here (and disallow values outside the int32_t range).
@@ -357,6 +305,18 @@
   DONE,
 };
 
+// The major types from RFC 7049 Section 2.1.
+enum class MajorType {
+  UNSIGNED = 0,
+  NEGATIVE = 1,
+  BYTE_STRING = 2,
+  STRING = 3,
+  ARRAY = 4,
+  MAP = 5,
+  TAG = 6,
+  SIMPLE_VALUE = 7
+};
+
 // CBORTokenizer segments a CBOR message, presenting the tokens therein as
 // numbers, strings, etc. This is not a complete CBOR parser, but makes it much
 // easier to implement one (e.g. ParseCBOR, above). It can also be used to parse
@@ -403,6 +363,9 @@
   // To be called only if ::TokenTag() == CBORTokenTag::BINARY.
   span<uint8_t> GetBinary() const;
 
+  // To be called only if ::TokenTag() == CBORTokenTag::ENVELOPE.
+  span<uint8_t> GetEnvelopeContents() const;
+
  private:
   void ReadNextToken(bool enter_envelope);
   void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length);
@@ -412,14 +375,72 @@
   CBORTokenTag token_tag_;
   struct Status status_;
   std::ptrdiff_t token_byte_length_;
-  cbor::MajorType token_start_type_;
+  MajorType token_start_type_;
   uint64_t token_start_internal_value_;
 };
 
-void DumpCBOR(span<uint8_t> cbor);
+// =============================================================================
+// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
+// =============================================================================
 
+// Parses a CBOR encoded message from |bytes|, sending events to
+// |out|. If an error occurs, sends |out->HandleError|, and parsing stops.
+// The client is responsible for discarding the already received information in
+// that case.
+void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out);
+
+namespace internals {  // Exposed only for writing tests.
+int8_t ReadTokenStart(span<uint8_t> bytes,
+                      cbor::MajorType* type,
+                      uint64_t* value);
+
+void WriteTokenStart(cbor::MajorType type,
+                     uint64_t value,
+                     std::vector<uint8_t>* encoded);
+}  // namespace internals
+}  // namespace cbor
+
+namespace json {
+// Client code must provide an instance. Implementation should delegate
+// to whatever is appropriate.
+class Platform {
+ public:
+  virtual ~Platform() = default;
+  // Parses |str| into |result|. Returns false iff there are
+  // leftover characters or parsing errors.
+  virtual bool StrToD(const char* str, double* result) const = 0;
+
+  // Prints |value| in a format suitable for JSON.
+  virtual std::unique_ptr<char[]> DToStr(double value) const = 0;
+};
+
+// =============================================================================
+// json::NewJSONEncoder - for encoding streaming parser events as JSON
+// =============================================================================
+
+// Returns a handler object which will write ascii characters to |out|.
+// |status->ok()| will be false iff the handler routine HandleError() is called.
+// In that case, we'll stop emitting output.
+// Except for calling the HandleError routine at any time, the client
+// code must call the Handle* methods in an order in which they'd occur
+// in valid JSON; otherwise we may crash (the code uses assert).
+std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform,
+                                                       std::string* out,
+                                                       Status* status);
+
+// =============================================================================
+// json::ParseJSON - for receiving streaming parser events for JSON
+// =============================================================================
+
+void ParseJSON(const Platform* platform,
+               span<uint8_t> chars,
+               StreamingParserHandler* handler);
+void ParseJSON(const Platform* platform,
+               span<uint16_t> chars,
+               StreamingParserHandler* handler);
+}  // namespace json
 
 {% for namespace in config.protocol.namespace %}
 } // namespace {{namespace}}
 {% endfor %}
-#endif // !defined({{"_".join(config.protocol.namespace)}}_CBOR_h)
+#endif // !defined({{"_".join(config.protocol.namespace)}}_encoding_h)
diff --git a/third_party/inspector_protocol/roll.py b/third_party/inspector_protocol/roll.py
index 59699e6..deb1b28 100755
--- a/third_party/inspector_protocol/roll.py
+++ b/third_party/inspector_protocol/roll.py
@@ -13,7 +13,6 @@
 
 
 FILES_TO_SYNC = [
-    'BUILD.gn',
     'README.md',
     'check_protocol_compatibility.py',
     'code_generator.py',
diff --git a/third_party/libjingle_xmpp/README.chromium b/third_party/libjingle_xmpp/README.chromium
index 5ae9ef2..23aaef4e 100644
--- a/third_party/libjingle_xmpp/README.chromium
+++ b/third_party/libjingle_xmpp/README.chromium
@@ -21,8 +21,4 @@
 unused in Chromium, it's OK to delete it.
 
 Local Modifications:
-* Include paths in third_party/libjingle_xmpp/xmllite,
-  third_party/libjingle_xmpp/xmpp, and third_party/libjingle_xmpp/task_runner
-  are updated to reflect the new absolute paths to their own and webrtc's
-  headers.
-* disabled unstarted_task_test.DoNotDeleteTask2 under ASan
+This code does not exist in an upstream repo anymore.
diff --git a/third_party/libjingle_xmpp/xmpp/xmppclient.cc b/third_party/libjingle_xmpp/xmpp/xmppclient.cc
index 8a19078..de92055 100644
--- a/third_party/libjingle_xmpp/xmpp/xmppclient.cc
+++ b/third_party/libjingle_xmpp/xmpp/xmppclient.cc
@@ -111,7 +111,7 @@
   // For other servers, we leave the strings empty, which causes the jid's
   // domain to be used.  We do the same for gmail.com and googlemail.com as the
   // returned CN matches the account domain in those cases.
-  std::string server_name = settings.server().ToString();
+  std::string server_name = settings.server().host();
   if (server_name == jingle_xmpp::STR_TALK_GOOGLE_COM ||
       server_name == jingle_xmpp::STR_TALKX_L_GOOGLE_COM ||
       server_name == jingle_xmpp::STR_XMPP_GOOGLE_COM ||
diff --git a/third_party/robolectric/BUILD.gn b/third_party/robolectric/BUILD.gn
index c6ca0b5..50a63f4 100644
--- a/third_party/robolectric/BUILD.gn
+++ b/third_party/robolectric/BUILD.gn
@@ -912,7 +912,7 @@
     ":robolectric_utils_java",
     ":shadows_core_java",
     "//build/android:sun_tools_java",
-    "//third_party/android_deps:android_support_multidex_java",
+    "//third_party/android_deps:com_android_support_multidex_java",
     "//third_party/gson:gson_java",
     "//third_party/guava:guava_java",
   ]
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c
index 911b658..1b990ba6 100644
--- a/third_party/sqlite/amalgamation/sqlite3.c
+++ b/third_party/sqlite/amalgamation/sqlite3.c
@@ -57716,8 +57716,12 @@
   */
   pPg->flags &= ~PGHDR_NEED_SYNC;
   pPgOld = sqlite3PagerLookup(pPager, pgno);
-  assert( !pPgOld || pPgOld->nRef==1 );
+  assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
   if( pPgOld ){
+    if( pPgOld->nRef>1 ){
+      sqlite3PagerUnrefNotNull(pPgOld);
+      return SQLITE_CORRUPT_BKPT;
+    }
     pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
     if( pPager->tempFile ){
       /* Do not discard pages from an in-memory database since we might
@@ -221520,7 +221524,7 @@
 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
 
 /************** End of stmt.c ************************************************/
-#if __LINE__!=221523
+#if __LINE__!=221527
 #undef SQLITE_SOURCE_ID
 #define SQLITE_SOURCE_ID      "2019-02-25 16:06:06 bd49a8271d650fa89e446b42e513b595a717b9212c91dd384aab871fc1d0alt2"
 #endif
diff --git a/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch b/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
index 40932de..a881277c 100644
--- a/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
+++ b/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: dumi <dumi@chromium.org>
 Date: Mon, 20 Jul 2009 23:40:51 +0000
-Subject: [PATCH 01/10] Modify default VFS to support WebDatabase.
+Subject: [PATCH 01/11] Modify default VFS to support WebDatabase.
 
 The renderer WebDatabase implementation needs to broker certain requests
 to the browser.  This modifies SQLite to allow monkey-patching the VFS
@@ -175,5 +175,5 @@
  ** CAPI3REF: String LIKE Matching
  *
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
index e05110e..a79a522d 100644
--- a/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
+++ b/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Scott Hess <shess@chromium.org>
 Date: Sat, 20 Jul 2013 11:42:21 -0700
-Subject: [PATCH 02/10] Virtual table supporting recovery of corrupted
+Subject: [PATCH 02/11] Virtual table supporting recovery of corrupted
  databases.
 
 "recover" implements a virtual table which uses the SQLite pager layer
@@ -3901,5 +3901,5 @@
 +
 +finish_test
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
index 2396150..b0a16fe 100644
--- a/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
+++ b/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: "tc@google.com" <tc@google.com>
 Date: Tue, 6 Jan 2009 22:39:41 +0000
-Subject: [PATCH 03/10] Custom shell.c helpers to load Chromium's ICU data.
+Subject: [PATCH 03/11] Custom shell.c helpers to load Chromium's ICU data.
 
 History uses fts3 with an icu-based segmenter.  These changes allow building a
 sqlite3 binary for Linux or Windows which can read those files.
@@ -141,5 +141,5 @@
 +  return 1;
 +}
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch b/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
index f0c5125e..67eb49c 100644
--- a/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
+++ b/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Scott Hess <shess@chromium.org>
 Date: Tue, 16 Dec 2014 13:02:27 -0800
-Subject: [PATCH 04/10] [fts3] Disable fts3_tokenizer and fts4.
+Subject: [PATCH 04/11] [fts3] Disable fts3_tokenizer and fts4.
 
 fts3_tokenizer allows a SQLite user to specify a pointer to call as a
 function, which has obvious sercurity implications.  Disable fts4 until
@@ -56,5 +56,5 @@
    }
  
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch b/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
index 70172d6..8d6ff4b9 100644
--- a/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
+++ b/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Scott Graham <scottmg@chromium.org>
 Date: Mon, 11 Sep 2017 13:37:46 -0700
-Subject: [PATCH 05/10] fuchsia: Use dot-file locking for sqlite
+Subject: [PATCH 05/11] fuchsia: Use dot-file locking for sqlite
 
 ---
  third_party/sqlite/src/src/os_unix.c | 4 ++++
@@ -23,5 +23,5 @@
      UNIXVFS("unix",          posixIoFinder ),
  #endif
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch b/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch
index b1f49d81..129309c1 100644
--- a/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch
+++ b/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 10 Feb 2019 13:12:57 -0800
-Subject: [PATCH 06/10] Fix compilation with SQLITE_OMIT_WINDOWFUNC.
+Subject: [PATCH 06/11] Fix compilation with SQLITE_OMIT_WINDOWFUNC.
 
 ---
  third_party/sqlite/src/src/resolve.c | 2 ++
@@ -28,5 +28,5 @@
      /* If this is part of a compound SELECT, check that it has the right
      ** number of expressions in the select list. */
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch b/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch
index ad34409..7cc4db65 100644
--- a/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch
+++ b/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 10 Feb 2019 15:18:43 -0800
-Subject: [PATCH 07/10] Fix dbfuzz2.c compilation errors on Windows.
+Subject: [PATCH 07/11] Fix dbfuzz2.c compilation errors on Windows.
 
 ---
  third_party/sqlite/src/test/dbfuzz2.c | 4 ++++
@@ -39,5 +39,5 @@
      argv[j++] = argv[i];
    }
 -- 
-2.21.0.352.gf09ad66450-goog
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0008-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch b/third_party/sqlite/patches/0008-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch
index 456c8b1c..78c5dd9 100644
--- a/third_party/sqlite/patches/0008-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch
+++ b/third_party/sqlite/patches/0008-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Darwin Huang <huangdarwin@chromium.org>
 Date: Tue, 5 Mar 2019 13:49:51 -0800
-Subject: [PATCH 08/10] Fix Heap-buffer-overflow in vdbeRecordCompareInt
+Subject: [PATCH 08/11] Fix Heap-buffer-overflow in vdbeRecordCompareInt
 
 This backports https://www.sqlite.org/src/info/c1ac00706bae45fe
 
@@ -23,6 +23,6 @@
            sqlite3_free(pCellKey);
          }
          assert(
---
-2.21.0.352.gf09ad66450-goog
+-- 
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0009-fix-heap-buffer-overflow-in-cellsizeptr.patch b/third_party/sqlite/patches/0009-fix-heap-buffer-overflow-in-cellsizeptr.patch
index f597a3e..56044458 100644
--- a/third_party/sqlite/patches/0009-fix-heap-buffer-overflow-in-cellsizeptr.patch
+++ b/third_party/sqlite/patches/0009-fix-heap-buffer-overflow-in-cellsizeptr.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Darwin Huang <huangdarwin@chromium.org>
 Date: Tue, 5 Mar 2019 14:13:19 -0800
-Subject: [PATCH 09/10] fix heap-buffer-overflow in cellsizeptr
+Subject: [PATCH 09/11] fix heap-buffer-overflow in cellsizeptr
 
 This backports https://www.sqlite.org/src/info/e7aca0714bc475e0
 
@@ -29,8 +29,8 @@
 +        memset(pNew+pageSize, 0, 8);
 +      }
      }
-
+ 
      if( rc==SQLITE_OK ){
---
-2.21.0.352.gf09ad66450-goog
+-- 
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0010-fix-integer-overflow-in-checkList.patch b/third_party/sqlite/patches/0010-fix-integer-overflow-in-checkList.patch
index e909a7f..80c10bc 100644
--- a/third_party/sqlite/patches/0010-fix-integer-overflow-in-checkList.patch
+++ b/third_party/sqlite/patches/0010-fix-integer-overflow-in-checkList.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Darwin Huang <huangdarwin@chromium.org>
 Date: Tue, 5 Mar 2019 14:17:05 -0800
-Subject: [PATCH 10/10] fix integer overflow in checkList
+Subject: [PATCH 10/11] fix integer overflow in checkList
 
 This backports https://www.sqlite.org/src/info/05b87e0755638d31
 
@@ -28,7 +28,7 @@
    while( iPage!=0 && pCheck->mxErr ){
      DbPage *pOvflPage;
 @@ -9797,7 +9797,7 @@ static int checkTreePage(
-
+ 
      /* Check the content overflow list */
      if( info.nPayload>info.nLocal ){
 -      int nPage;       /* Number of pages on the overflow chain */
@@ -36,6 +36,6 @@
        Pgno pgnoOvfl;   /* First page of the overflow chain */
        assert( pc + info.nSize - 4 <= usableSize );
        nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
---
-2.21.0.352.gf09ad66450-goog
+-- 
+2.21.0.225.g810b269d1ac-goog
 
diff --git a/third_party/sqlite/patches/0011-Fix-Heap-use-after-free-in-releasePageNotNull.patch b/third_party/sqlite/patches/0011-Fix-Heap-use-after-free-in-releasePageNotNull.patch
new file mode 100644
index 0000000..dca77bc
--- /dev/null
+++ b/third_party/sqlite/patches/0011-Fix-Heap-use-after-free-in-releasePageNotNull.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Darwin Huang <huangdarwin@chromium.org>
+Date: Tue, 12 Mar 2019 17:30:33 -0700
+Subject: [PATCH 11/11] Fix Heap-use-after-free in releasePageNotNull
+
+This backports https://www.sqlite.org/src/info/b0d5cf40bba34e45
+
+Bug: 936719
+---
+ third_party/sqlite/src/src/pager.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/pager.c b/third_party/sqlite/src/src/pager.c
+index efb9155f545d..6c21cc6172b9 100644
+--- a/third_party/sqlite/src/src/pager.c
++++ b/third_party/sqlite/src/src/pager.c
+@@ -7174,8 +7174,12 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
+   */
+   pPg->flags &= ~PGHDR_NEED_SYNC;
+   pPgOld = sqlite3PagerLookup(pPager, pgno);
+-  assert( !pPgOld || pPgOld->nRef==1 );
++  assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
+   if( pPgOld ){
++    if( pPgOld->nRef>1 ){
++      sqlite3PagerUnrefNotNull(pPgOld);
++      return SQLITE_CORRUPT_BKPT;
++    }
+     pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+     if( pPager->tempFile ){
+       /* Do not discard pages from an in-memory database since we might
+--
+2.21.0.225.g810b269d1ac-goog
+
diff --git a/third_party/sqlite/src/src/pager.c b/third_party/sqlite/src/src/pager.c
index efb9155..6c21cc6 100644
--- a/third_party/sqlite/src/src/pager.c
+++ b/third_party/sqlite/src/src/pager.c
@@ -7174,8 +7174,12 @@
   */
   pPg->flags &= ~PGHDR_NEED_SYNC;
   pPgOld = sqlite3PagerLookup(pPager, pgno);
-  assert( !pPgOld || pPgOld->nRef==1 );
+  assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
   if( pPgOld ){
+    if( pPgOld->nRef>1 ){
+      sqlite3PagerUnrefNotNull(pPgOld);
+      return SQLITE_CORRUPT_BKPT;
+    }
     pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
     if( pPager->tempFile ){
       /* Do not discard pages from an in-memory database since we might
diff --git a/tools/android/audio_focus_grabber/BUILD.gn b/tools/android/audio_focus_grabber/BUILD.gn
index a7236f4..b05e9111 100644
--- a/tools/android/audio_focus_grabber/BUILD.gn
+++ b/tools/android/audio_focus_grabber/BUILD.gn
@@ -12,7 +12,7 @@
   deps = [
     ":audio_focus_grabber_apk_resources",
     "//base:base_java",
-    "//third_party/android_deps:android_support_compat_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
   ]
 
   java_files = [
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index 892526f..ee54015 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -1117,28 +1117,23 @@
   return section_sizes, 0
 
 
-def _ParseDexSymbols(section_sizes, apk_path, mapping_path, size_info_prefix,
-                     output_directory):
-  symbols = apkanalyzer.CreateDexSymbols(
-      apk_path, mapping_path, size_info_prefix, output_directory)
-  prev = section_sizes.setdefault(models.SECTION_DEX, 0)
-  section_sizes[models.SECTION_DEX] = prev + sum(s.size for s in symbols)
-  return symbols
-
-
 def _ParseApkOtherSymbols(section_sizes, apk_path, apk_so_path,
                           size_info_prefix, knobs):
   res_source_mapper = _ResourceSourceMapper(size_info_prefix, knobs)
   apk_symbols = []
+  dex_size = 0
   zip_info_total = 0
   with zipfile.ZipFile(apk_path) as z:
     for zip_info in z.infolist():
       zip_info_total += zip_info.compress_size
       # Skip main shared library, pak, and dex files as they are accounted for.
       if (zip_info.filename == apk_so_path
-          or zip_info.filename.endswith('.dex')
           or zip_info.filename.endswith('.pak')):
         continue
+      if zip_info.filename.endswith('.dex'):
+        dex_size += zip_info.file_size
+        continue
+
       source_path = res_source_mapper.FindSourceForPath(zip_info.filename)
       if source_path is None:
         source_path = os.path.join(models.APK_PREFIX_PATH, zip_info.filename)
@@ -1153,7 +1148,8 @@
   apk_symbols.append(zip_overhead_symbol)
   prev = section_sizes.setdefault(models.SECTION_OTHER, 0)
   section_sizes[models.SECTION_OTHER] = prev + sum(s.size for s in apk_symbols)
-  return apk_symbols
+
+  return dex_size, apk_symbols
 
 
 def _CreatePakObjectMap(object_paths_by_name):
@@ -1316,15 +1312,21 @@
           section_sizes, metadata, apk_elf_result)
     pak_symbols_by_id = _FindPakSymbolsFromApk(
         section_sizes, apk_path, size_info_prefix, knobs)
-    raw_symbols.extend(
-        _ParseDexSymbols(section_sizes,
-                         apk_path,
-                         mapping_path,
-                         size_info_prefix,
-                         output_directory))
-    raw_symbols.extend(
-        _ParseApkOtherSymbols(section_sizes, apk_path, apk_so_path,
-                              size_info_prefix, knobs))
+    dex_symbols = apkanalyzer.CreateDexSymbols(
+        apk_path, mapping_path, size_info_prefix, output_directory)
+    raw_symbols.extend(dex_symbols)
+    dex_size, other_symbols = _ParseApkOtherSymbols(
+        section_sizes, apk_path, apk_so_path, size_info_prefix, knobs)
+    raw_symbols.extend(other_symbols)
+
+    # We can't meaningfully track section size of dex methods vs other, so just
+    # fake the size of dex methods as the sum of symbols, and make "dex other"
+    # responsible for any unattributed bytes.
+    dex_method_size = int(round(sum(
+        s.pss for s in dex_symbols
+        if s.section_name == models.SECTION_DEX_METHOD)))
+    section_sizes[models.SECTION_DEX_METHOD] = dex_method_size
+    section_sizes[models.SECTION_DEX] = dex_size - dex_method_size
   elif pak_files and pak_info_file:
     pak_symbols_by_id = _FindPakSymbolsFromFiles(
         section_sizes, pak_files, pak_info_file, output_directory)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
index c992b9c7..8fd9e75 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
@@ -40,12 +40,12 @@
 * 6 have source paths. Accounts for 524520 bytes (100.0%).
 * 0 symbols have shared ownership.
 * 3 symbols are from generated sources. Accounts for 232 bytes (0.0%).
-Section .dex: has 99.7% of 8365003 bytes accounted for from 93 symbols. 23605 bytes are unaccounted for.
+Section .dex: has 100.0% of 8365003 bytes accounted for from 93 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
 * 83 have source paths. Accounts for 926 bytes (0.0%).
 * 1 placeholders exist (symbols that start with **). Accounts for 4616803 bytes (55.2%).
 * 0 symbols have shared ownership.
-Section .dex.method: 23605 bytes from 100 symbols.
+Section .dex.method: has 100.0% of 23605 bytes accounted for from 100 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
 * 90 have source paths. Accounts for 21154 bytes (89.6%).
 * 0 symbols have shared ownership.
diff --git a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
index 102c8a8..12371d0f 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
@@ -41,12 +41,12 @@
 * 6 have source paths. Accounts for 524520 bytes (100.0%).
 * 0 symbols have shared ownership.
 * 3 symbols are from generated sources. Accounts for 232 bytes (0.0%).
-Section .dex: has 99.7% of 8365003 bytes accounted for from 93 symbols. 23605 bytes are unaccounted for.
+Section .dex: has 100.0% of 8365003 bytes accounted for from 93 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
 * 83 have source paths. Accounts for 926 bytes (0.0%).
 * 1 placeholders exist (symbols that start with **). Accounts for 4616803 bytes (55.2%).
 * 0 symbols have shared ownership.
-Section .dex.method: 23605 bytes from 100 symbols.
+Section .dex.method: has 100.0% of 23605 bytes accounted for from 100 symbols. 0 bytes are unaccounted for.
 * Padding accounts for 0 bytes (0.0%)
 * 90 have source paths. Accounts for 21154 bytes (89.6%).
 * 0 symbols have shared ownership.
diff --git a/tools/chrome_proxy/webdriver/emulation_server.py b/tools/chrome_proxy/webdriver/emulation_server.py
index 9975046..1de9846 100644
--- a/tools/chrome_proxy/webdriver/emulation_server.py
+++ b/tools/chrome_proxy/webdriver/emulation_server.py
@@ -140,7 +140,7 @@
 
   # Create a private key pair.
   pk = crypto.PKey()
-  pk.generate_key(crypto.TYPE_RSA, 1024)
+  pk.generate_key(crypto.TYPE_RSA, 3072)
 
   # Create a certificate and sign it.
   cert = crypto.X509()
diff --git a/tools/chrome_proxy/webdriver/proxy_connection.py b/tools/chrome_proxy/webdriver/proxy_connection.py
index 192ad88..984bd9b 100644
--- a/tools/chrome_proxy/webdriver/proxy_connection.py
+++ b/tools/chrome_proxy/webdriver/proxy_connection.py
@@ -6,6 +6,7 @@
 from common import TestDriver
 from common import IntegrationTest
 from decorators import ChromeVersionBetweenInclusiveM
+from decorators import ChromeVersionEqualOrAfterM
 from emulation_server import BlackHoleHandler
 from emulation_server import InvalidTLSHandler
 from emulation_server import TCPResetHandler
@@ -13,7 +14,7 @@
 
 class ProxyConnection(IntegrationTest):
 
-  @ChromeVersionBetweenInclusiveM(63, 72)
+  @ChromeVersionEqualOrAfterM(63)
   def testTLSInjectionAfterHandshake(self):
     port = common.GetOpenPort()
     with TestDriver() as t:
@@ -25,6 +26,8 @@
         '--data-reduction-proxy-http-proxies=https://127.0.0.1:%d' % port)
       t.AddChromeArg(
         '--force-fieldtrials=DataReductionProxyConfigService/Disabled')
+      t.AddChromeArg(
+        '--enable-features=NetworkService,DataReductionProxyEnabledWithNetworkService')
       t.UseEmulationServer(InvalidTLSHandler, port=port)
 
       t.LoadURL('http://check.googlezip.net/test.html')
@@ -37,7 +40,7 @@
       self.assertTrue(t.SleepUntilHistogramHasEntry('DataReductionProxy.'
         'InvalidResponseHeadersReceived.NetError'))
 
-  @ChromeVersionBetweenInclusiveM(63, 72)
+  @ChromeVersionEqualOrAfterM(63)
   def testTCPReset(self):
     port = common.GetOpenPort()
     with TestDriver() as t:
@@ -50,6 +53,8 @@
         '--data-reduction-proxy-http-proxies=http://127.0.0.1:%d' % port)
       t.AddChromeArg(
         '--force-fieldtrials=DataReductionProxyConfigService/Disabled')
+      t.AddChromeArg(
+        '--enable-features=NetworkService,DataReductionProxyEnabledWithNetworkService')
       t.UseEmulationServer(TCPResetHandler, port=port)
 
       t.LoadURL('http://check.googlezip.net/test.html')
@@ -62,7 +67,7 @@
       self.assertTrue(t.SleepUntilHistogramHasEntry('DataReductionProxy.'
         'InvalidResponseHeadersReceived.NetError'))
 
-  @ChromeVersionBetweenInclusiveM(63, 72)
+  @ChromeVersionEqualOrAfterM(63)
   def testTLSReset(self):
     port = common.GetOpenPort()
     with TestDriver() as t:
@@ -75,6 +80,8 @@
         '--data-reduction-proxy-http-proxies=https://127.0.0.1:%d' % port)
       t.AddChromeArg(
         '--force-fieldtrials=DataReductionProxyConfigService/Disabled')
+      t.AddChromeArg(
+        '--enable-features=NetworkService,DataReductionProxyEnabledWithNetworkService')
       t.UseEmulationServer(TLSResetHandler, port=port)
 
       t.LoadURL('http://check.googlezip.net/test.html')
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3c61fcc0..6692cac 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -33038,6 +33038,7 @@
   <int value="537857256" label="PipRoundedCorners:enabled"/>
   <int value="538468149" label="OfflinePagesCT:enabled"/>
   <int value="538600423" label="OmniboxDocumentProvider:enabled"/>
+  <int value="538685995" label="InstallableInkDrop:enabled"/>
   <int value="546043947" label="ImplicitRootScroller:enabled"/>
   <int value="546520086" label="enable-data-reduction-proxy-savings-promo"/>
   <int value="546710806" label="disable-easy-signin"/>
@@ -33419,6 +33420,7 @@
   <int value="1167613030" label="enable-permission-action-reporting"/>
   <int value="1169418814" label="ManualFallbacksFilling:enabled"/>
   <int value="1174088940" label="enable-wasm"/>
+  <int value="1177120582" label="InstallableInkDrop:disabled"/>
   <int value="1179013979"
       label="OmniboxUIExperimentMaxAutocompleteMatches:enabled"/>
   <int value="1179936481" label="enable-android-pay-integration-v1"/>
@@ -44341,6 +44343,7 @@
   <int value="55" label="CREDENTIAL_MANAGER_API"/>
   <int value="56" label="NOSTATE_PREFETCH_FINISHED"/>
   <int value="57" label="LOW_END_DEVICE"/>
+  <int value="58" label="FINAL_STATUS_BROWSER_SWITCH"/>
 </enum>
 
 <enum name="PrerenderHoverEvent">
@@ -44495,6 +44498,17 @@
   <int value="8" label="PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP"/>
 </enum>
 
+<enum name="PrerenderOrigin">
+  <int value="2" label="ORIGIN_GWS_PRERENDER"/>
+  <int value="5" label="ORIGIN_OMNIBOX"/>
+  <int value="6" label="ORIGIN_NONE"/>
+  <int value="7" label="ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN"/>
+  <int value="8" label="ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN"/>
+  <int value="10" label="ORIGIN_EXTERNAL_REQUEST"/>
+  <int value="12" label="ORIGIN_LINK_REL_NEXT"/>
+  <int value="13" label="ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER"/>
+</enum>
+
 <enum name="PrerenderPageviewEvents">
   <obsolete>
     deprecated Nov 16 2012
@@ -48685,6 +48699,9 @@
 </enum>
 
 <enum name="ServiceWorkerContextRequestHandlerStatus">
+  <obsolete>
+    No longer recorded since NetS13nSW shipped on Dec 2018.
+  </obsolete>
   <summary>
     The result of ServiceWorkerContextHandler handling a request for a service
     worker script. From ServiceWorkerContextHandler::CreateJobStatus.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 8c930eb..1322d9f4 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3920,6 +3920,16 @@
   </summary>
 </histogram>
 
+<histogram name="Apps.AppListSearchAbandonQueryLength" units="characters"
+    expires_after="2019-12-31">
+  <owner>jennyz@chromium.org</owner>
+  <owner>jiameng@chromium.org</owner>
+  <summary>
+    The length of the query when the user abandons results of a queried search
+    or recommendations of zero state (zero length query) in launcher UI.
+  </summary>
+</histogram>
+
 <histogram name="Apps.AppListSearchBoxActivated"
     enum="SearchBoxActivationSource">
   <owner>newcomer@chromium.org</owner>
@@ -5444,6 +5454,47 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Overview.AnimationSmoothness.Close" units="%"
+    expires_after="M77">
+<!-- Name completed by histogram_suffixes
+     name="TabletOrClamshellMode" -->
+
+  <owner>omrilio@chromium.org</owner>
+  <owner>oshima@chromium.org</owner>
+  <summary>
+    Relative smoothness of animations when closing a window, recorded when the
+    animation completes. 100% represents ideally smooth 60 frames per second.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.AnimationSmoothness.Enter" units="%"
+    expires_after="M77">
+<!-- Name completed by histogram_suffixes
+     name="TabletOrClamshellMode" -->
+
+  <owner>omrilio@chromium.org</owner>
+  <owner>oshima@chromium.org</owner>
+  <summary>
+    Relative smoothness of animations when entering overview mode, recorded when
+    the animation completes. 100% represents ideally smooth 60 frames per
+    second.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.AnimationSmoothness.Exit" units="%"
+    expires_after="M77">
+<!-- Name completed by histogram_suffixes
+     name="TabletOrClamshellMode" -->
+
+  <owner>omrilio@chromium.org</owner>
+  <owner>oshima@chromium.org</owner>
+  <summary>
+    Relative smoothness of animations when exiting overview mode, recorded when
+    the animation completes. 100% represents ideally smooth 60 frames per
+    second.
+  </summary>
+</histogram>
+
 <histogram name="Ash.PersistentWindow.NumOfWindowsRestored">
   <owner>warx@chromium.org</owner>
   <summary>
@@ -6119,25 +6170,40 @@
   </summary>
 </histogram>
 
-<histogram name="Ash.WindowSelector.AnimationSmoothness.Close" units="%">
+<histogram base="true" name="Ash.WindowSelector.AnimationSmoothness.Close"
+    units="%" expires_after="M77">
   <owner>estade@chromium.org</owner>
   <summary>
+    Deprecated 03/2019 in favor of
+    Ash.Overview.AnimationSmoothness.Close.Clamshell and
+    Ash.Overview.AnimationSmoothness.Close.Tablet
+
     Relative smoothness of animations when closing a window in overview mode.
     100% represents ideally smooth 60 frames per second.
   </summary>
 </histogram>
 
-<histogram name="Ash.WindowSelector.AnimationSmoothness.Enter" units="%">
+<histogram base="true" name="Ash.WindowSelector.AnimationSmoothness.Enter"
+    units="%" expires_after="M77">
   <owner>estade@chromium.org</owner>
   <summary>
+    Deprecated 03/2019 in favor of
+    Ash.Overview.AnimationSmoothness.Enter.Clamshell and
+    Ash.Overview.AnimationSmoothness.Enter.Tablet
+
     Relative smoothness of animations when entering overview mode. 100%
     represents ideally smooth 60 frames per second.
   </summary>
 </histogram>
 
-<histogram name="Ash.WindowSelector.AnimationSmoothness.Exit" units="%">
+<histogram base="true" name="Ash.WindowSelector.AnimationSmoothness.Exit"
+    units="%" expires_after="M77">
   <owner>estade@chromium.org</owner>
   <summary>
+    Deprecated 03/2019 in favor of
+    Ash.Overview.AnimationSmoothness.Exit.Clamshell and
+    Ash.Overview.AnimationSmoothness.Exit.Tablet
+
     Relative smoothness of animations when exiting overview mode. 100%
     represents ideally smooth 60 frames per second.
   </summary>
@@ -9565,6 +9631,24 @@
   </details>
 </histogram>
 
+<histogram name="Autofill.WalletUseDate.Address" units="ms" expires_after="M76">
+  <owner>jkrcal@chromium.org</owner>
+  <owner>treib@chromium.org</owner>
+  <summary>
+    The time since last use date of a wallet address, as known by sync. Recorded
+    for each wallet address on startup.
+  </summary>
+</histogram>
+
+<histogram name="Autofill.WalletUseDate.Card" units="ms" expires_after="M76">
+  <owner>jkrcal@chromium.org</owner>
+  <owner>treib@chromium.org</owner>
+  <summary>
+    The time since last use date of a wallet card, as known by sync. Recorded
+    for each wallet card on startup.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.WebView.AutofillSession" enum="AutofillSessionStates">
   <owner>michaelbai@chromium.org</owner>
   <summary>Records the state of an autofill session.</summary>
@@ -101237,6 +101321,15 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientDownload.ZipTooBigToUnpack" enum="Boolean">
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records whether a given ZIP download was too big to unpack, as specified by
+    configuration option set in SafeBrowsing download service. This metric is
+    logged each time the user downloads a ZIP file.
+  </summary>
+</histogram>
+
 <histogram name="SBClientMalware.ClassificationStart" enum="BooleanHit">
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -105762,6 +105855,9 @@
 
 <histogram name="ServiceWorker.ContextRequestHandlerStatus"
     enum="ServiceWorkerContextRequestHandlerStatus">
+  <obsolete>
+    No longer recorded since NetS13nSW shipped on Dec 2018.
+  </obsolete>
   <owner>falken@chromium.org</owner>
   <summary>
     The result of ServiceWorkerContextRequestHandler handling a request for a
@@ -146385,6 +146481,9 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="ServiceWorker.ContextRequestType" separator=".">
+  <obsolete>
+    The affected histogram is obsolete.
+  </obsolete>
   <suffix name="InstalledWorker.ImportedScript"
       label="Imported script for an installed worker"/>
   <suffix name="InstalledWorker.MainScript"
@@ -147836,6 +147935,9 @@
   <suffix name="TabletMode" label="Tablet Mode Enabled"/>
   <affected-histogram name="Apps.AppListFolderNameLength"/>
   <affected-histogram name="Apps.StateTransition.AnimationSmoothness"/>
+  <affected-histogram name="Ash.Overview.AnimationSmoothness.Close"/>
+  <affected-histogram name="Ash.Overview.AnimationSmoothness.Enter"/>
+  <affected-histogram name="Ash.Overview.AnimationSmoothness.Exit"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="TabNewTabOnload" separator=".">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 89d4f0f..7235797f 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -4279,6 +4279,39 @@
   </metric>
 </event>
 
+<event name="NoStatePrefetch" singular="True">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    Metrics related to NoStatePrefetch that are recorded using the same UKM IDs
+    as PageLoad.
+  </summary>
+  <metric name="PrefetchedRecently.FinalStatus">
+    <summary>
+      Final status of the nostate prefetch if one was recently attempted for
+      either the committed URL of this navigation or for any URL in the redirect
+      chain for the main frame resource for this navigation. page. Recorded as
+      enum PrerenderFinalStatus in //tools/metrics/histograms/enums.xml.
+    </summary>
+  </metric>
+  <metric name="PrefetchedRecently.Origin">
+    <summary>
+      Triggering origin of the nostate prefetch if one was recently attempted
+      for either the committed URL of this navigation or for any URL in the
+      redirect chain for the main frame resource for this navigation. Recorded
+      as enum PrerenderOrigin in //tools/metrics/histograms/enums.xml.
+    </summary>
+  </metric>
+  <metric name="PrefetchedRecently.PrefetchAge">
+    <summary>
+      Records the time (in milliseconds) from the start of the nostate prefetch
+      to the time of commit of this navigation. Metric is recorded down to the
+      nearest power of 2. Recorded only if a nostate prefetch was recently
+      attempted for either the committed URL of this navigation or for any URL
+      in the redirect chain for the main frame resource for this navigation.
+    </summary>
+  </metric>
+</event>
+
 <event name="PageLoadCapping" singular="True">
   <owner>ryansturm@chromium.org</owner>
   <summary>
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr.py b/tools/perf/cli_tools/update_wpr/update_wpr.py
index b1d87d08..d7f0879 100644
--- a/tools/perf/cli_tools/update_wpr/update_wpr.py
+++ b/tools/perf/cli_tools/update_wpr/update_wpr.py
@@ -401,7 +401,7 @@
       if self._IsDesktop():
         configs = ['linux-perf', 'win-10-perf', 'mac-10_12_laptop_low_end-perf']
       else:
-        configs = ['Android Nexus5 Perf']
+        configs = ['android-nexus5x-perf']
     for config in configs:
       job_url = self._StartPinpointJob(config)
       if not job_url:
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index be1b751..17b9be0c 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -333,9 +333,9 @@
     ":ui_java_resources",
     ":ui_utils_java",
     "//base:base_java",
-    "//third_party/android_deps:android_support_annotations_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
-    "//third_party/android_deps:android_support_v7_recyclerview_java",
+    "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
   ]
   srcjar_deps = [
     ":java_enums_srcjar",
diff --git a/ui/aura/mus/client_side_window_move_handler.cc b/ui/aura/mus/client_side_window_move_handler.cc
index 7c3b6738..827f401 100644
--- a/ui/aura/mus/client_side_window_move_handler.cc
+++ b/ui/aura/mus/client_side_window_move_handler.cc
@@ -99,6 +99,12 @@
 
 void ClientSideWindowMoveHandler::MaybeSetupLastTarget(
     ui::LocatedEvent* event) {
+  // Do nothing in the middle of a dragging session, otherwise some properties
+  // (e.g. |last_component_| or |dragging_window_|) might get wrong. See:
+  // https://crbug.com/940545.
+  if (dragging_window_)
+    return;
+
   last_target_.RemoveAll();
 
   Window* window = GetToplevelTargetForEvent(event, &last_component_);
@@ -116,6 +122,11 @@
 
 void ClientSideWindowMoveHandler::UpdateWindowResizeShadow(Window* window,
                                                            int component) {
+  // Do nothing in the middle of a dragging session. See:
+  // https://crbug.com/940545.
+  if (dragging_window_)
+    return;
+
   client_->SetWindowResizeShadow(window->GetRootWindow(), component);
   last_shadow_target_.RemoveAll();
   last_shadow_target_.Add(window);
@@ -124,6 +135,11 @@
 void ClientSideWindowMoveHandler::MaybePerformWindowMove(
     ui::LocatedEvent* event,
     ws::mojom::MoveLoopSource source) {
+  // Do nothing in the middle of a dragging session. See:
+  // https://crbug.com/940545.
+  if (dragging_window_)
+    return;
+
   Window* target = static_cast<Window*>(event->target());
   if (!last_target_.Contains(target->GetToplevelWindow()))
     return;
diff --git a/ui/aura/mus/client_side_window_move_handler_unittest.cc b/ui/aura/mus/client_side_window_move_handler_unittest.cc
index b5d1f83..d9062f20 100644
--- a/ui/aura/mus/client_side_window_move_handler_unittest.cc
+++ b/ui/aura/mus/client_side_window_move_handler_unittest.cc
@@ -85,23 +85,24 @@
   }
   ~WindowMoveObserver() override { client_->RemoveTestObserver(this); }
 
-  bool in_window_move() const { return in_window_move_; }
+  bool in_window_move() const { return window_move_count_ > 0; }
+  int window_move_count() const { return window_move_count_; }
 
  private:
   // WindowTreeClientTestObserver:
   void OnChangeStarted(uint32_t change_id, ChangeType type) override {
     if (type == ChangeType::MOVE_LOOP)
-      in_window_move_ = true;
+      window_move_count_++;
   }
   void OnChangeCompleted(uint32_t change_id,
                          ChangeType type,
                          bool success) override {
     if (type == ChangeType::MOVE_LOOP)
-      in_window_move_ = false;
+      window_move_count_--;
   }
 
   WindowTreeClient* client_;
-  bool in_window_move_ = false;
+  int window_move_count_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(WindowMoveObserver);
 };
@@ -154,6 +155,13 @@
       event_generator_->PressTouch();
   }
 
+  void ReleaseInput() {
+    if (IsInputMouse())
+      event_generator_->ReleaseLeftButton();
+    else
+      event_generator_->ReleaseTouch();
+  }
+
   gfx::Rect GetWindowBounds() { return test_window_->GetBoundsInScreen(); }
 
   WindowMoveTestDelegate test_delegate_;
@@ -291,6 +299,38 @@
   EXPECT_FALSE(observer.in_window_move());
 }
 
+TEST_P(ClientSideWindowMoveHandlerTest,
+       AdditionalEventsShouldntTriggerAnotherMove) {
+  WindowMoveObserver observer(window_tree_client_impl());
+
+  MoveInputTo(GetWindowBounds().origin() + gfx::Vector2d(10, 10));
+
+  PressInput();
+  MoveInputBy(10, 10);
+  EXPECT_EQ(1, observer.window_move_count());
+  EXPECT_EQ(HTCAPTION, window_tree()->last_move_hit_test());
+  EXPECT_EQ(HTNOWHERE, window_tree()->last_window_resize_shadow());
+
+  // Nothing should happen for additional move events.
+  MoveInputBy(10, 10);
+  EXPECT_EQ(1, observer.window_move_count());
+  EXPECT_EQ(HTCAPTION, window_tree()->last_move_hit_test());
+  EXPECT_EQ(HTNOWHERE, window_tree()->last_window_resize_shadow());
+  window_tree()->AckAllChanges();
+  EXPECT_FALSE(observer.in_window_move());
+  ReleaseInput();
+
+  // Restarting a move should start a new move.
+  MoveInputTo(GetWindowBounds().origin() + gfx::Vector2d(10, 10));
+  PressInput();
+  MoveInputBy(10, 10);
+  EXPECT_EQ(1, observer.window_move_count());
+  EXPECT_EQ(HTCAPTION, window_tree()->last_move_hit_test());
+  EXPECT_EQ(HTNOWHERE, window_tree()->last_window_resize_shadow());
+  window_tree()->AckAllChanges();
+  EXPECT_FALSE(observer.in_window_move());
+}
+
 INSTANTIATE_TEST_SUITE_P(,
                          ClientSideWindowMoveHandlerTest,
                          ::testing::Values("mouse", "touch"));
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 85fa6c9..714ef6e 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -1726,7 +1726,12 @@
     const gfx::Point& cursor_location,
     int hit_test,
     base::OnceCallback<void(bool)> callback) {
-  DCHECK(on_current_move_finished_.is_null());
+  if (!on_current_move_finished_.is_null()) {
+    // Moving multiple windows at the same time is not allowed, and it causes
+    // troubles. See: https://crbug.com/940545.
+    std::move(callback).Run(false);
+    return;
+  }
   on_current_move_finished_ = std::move(callback);
 
   WindowMus* window_mus = WindowMus::Get(window_tree_host->window());
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index b614be2..798ae301 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -2712,6 +2712,31 @@
             window_tree()->last_transfer_new());
 }
 
+TEST_F(WindowTreeClientTest, SecondPerformWindowMoveIsNotAllowed) {
+  int call_count = 0;
+  bool last_result = false;
+
+  WindowTreeHostMus* host_mus = static_cast<WindowTreeHostMus*>(host());
+  host_mus->PerformWindowMove(
+      host_mus->window(), ws::mojom::MoveLoopSource::MOUSE, gfx::Point(),
+      HTCAPTION, base::BindOnce(&OnWindowMoveDone, &call_count, &last_result));
+  EXPECT_EQ(0, call_count);
+
+  int call_count_inner = 0;
+  bool inner_result = true;
+  host_mus->PerformWindowMove(
+      host_mus->window(), ws::mojom::MoveLoopSource::MOUSE, gfx::Point(),
+      HTCAPTION,
+      base::BindOnce(&OnWindowMoveDone, &call_count_inner, &inner_result));
+  EXPECT_EQ(0, call_count);
+  EXPECT_EQ(1, call_count_inner);
+  EXPECT_FALSE(inner_result);
+
+  window_tree()->AckAllChanges();
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(last_result);
+}
+
 // Verifies occlusion state from server is applied to underlying window.
 TEST_F(WindowTreeClientTest, OcclusionStateFromServer) {
   struct {
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 5775d95..7b59afbc 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -86,6 +86,7 @@
     "animation/ink_drop_state.h",
     "animation/ink_drop_stub.h",
     "animation/ink_drop_util.h",
+    "animation/installable_ink_drop.h",
     "animation/scroll_animator.h",
     "animation/square_ink_drop_ripple.h",
     "background.h",
@@ -297,6 +298,7 @@
     "animation/ink_drop_state.cc",
     "animation/ink_drop_stub.cc",
     "animation/ink_drop_util.cc",
+    "animation/installable_ink_drop.cc",
     "animation/scroll_animator.cc",
     "animation/square_ink_drop_ripple.cc",
     "background.cc",
@@ -992,6 +994,7 @@
     "animation/ink_drop_impl_unittest.cc",
     "animation/ink_drop_ripple_unittest.cc",
     "animation/ink_drop_unittest.cc",
+    "animation/installable_ink_drop_unittest.cc",
     "animation/square_ink_drop_ripple_unittest.cc",
     "border_unittest.cc",
     "bubble/bubble_border_unittest.cc",
diff --git a/ui/views/animation/ink_drop_event_handler.cc b/ui/views/animation/ink_drop_event_handler.cc
index 975728b..d9604eb 100644
--- a/ui/views/animation/ink_drop_event_handler.cc
+++ b/ui/views/animation/ink_drop_event_handler.cc
@@ -16,9 +16,13 @@
     : target_handler_(
           std::make_unique<ui::ScopedTargetHandler>(host_view, this)),
       host_view_(host_view),
-      delegate_(delegate) {}
+      delegate_(delegate) {
+  host_view_->AddObserver(this);
+}
 
-InkDropEventHandler::~InkDropEventHandler() = default;
+InkDropEventHandler::~InkDropEventHandler() {
+  host_view_->RemoveObserver(this);
+}
 
 void InkDropEventHandler::OnGestureEvent(ui::GestureEvent* event) {
   if (!host_view_->enabled() || !delegate_->SupportsGestureEvents())
@@ -86,4 +90,14 @@
   }
 }
 
+void InkDropEventHandler::OnViewFocused(View* observed_view) {
+  DCHECK_EQ(host_view_, observed_view);
+  delegate_->GetInkDrop()->SetFocused(true);
+}
+
+void InkDropEventHandler::OnViewBlurred(View* observed_view) {
+  DCHECK_EQ(host_view_, observed_view);
+  delegate_->GetInkDrop()->SetFocused(false);
+}
+
 }  // namespace views
diff --git a/ui/views/animation/ink_drop_event_handler.h b/ui/views/animation/ink_drop_event_handler.h
index 2abb6365..af15f2e 100644
--- a/ui/views/animation/ink_drop_event_handler.h
+++ b/ui/views/animation/ink_drop_event_handler.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "ui/events/event_handler.h"
+#include "ui/views/view_observer.h"
 #include "ui/views/views_export.h"
 
 namespace ui {
@@ -21,7 +22,8 @@
 enum class InkDropState;
 
 // This class handles ink-drop changes due to events on its host.
-class VIEWS_EXPORT InkDropEventHandler : public ui::EventHandler {
+class VIEWS_EXPORT InkDropEventHandler : public ui::EventHandler,
+                                         public ViewObserver {
  public:
   // Delegate class that allows InkDropEventHandler to be used with InkDrops
   // that are hosted in multiple ways.
@@ -48,6 +50,10 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
   void OnMouseEvent(ui::MouseEvent* event) override;
 
+  // ViewObserver:
+  void OnViewFocused(View* observed_view) override;
+  void OnViewBlurred(View* observed_view) override;
+
   // Allows |this| to handle all GestureEvents on |host_view_|.
   std::unique_ptr<ui::ScopedTargetHandler> target_handler_;
 
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 98abaa1c..967c513 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -22,29 +22,6 @@
 
 namespace views {
 
-class InkDropHostView::InkDropViewObserver : public ViewObserver {
- public:
-  explicit InkDropViewObserver(InkDropHostView* parent) : parent_(parent) {
-    parent_->AddObserver(this);
-  }
-  ~InkDropViewObserver() override { parent_->RemoveObserver(this); }
-  // ViewObserver:
-  void OnViewFocused(View* observed_view) override {
-    DCHECK_EQ(parent_, observed_view);
-    parent_->GetInkDrop()->SetFocused(true);
-  }
-
-  void OnViewBlurred(View* observed_view) override {
-    DCHECK_EQ(parent_, observed_view);
-    parent_->GetInkDrop()->SetFocused(false);
-  }
-
- private:
-  InkDropHostView* const parent_;
-
-  DISALLOW_COPY_AND_ASSIGN(InkDropViewObserver);
-};
-
 InkDropHostView::InkDropHostViewEventHandlerDelegate::
     InkDropHostViewEventHandlerDelegate(InkDropHostView* host_view)
     : host_view_(host_view) {}
@@ -65,8 +42,7 @@
 
 InkDropHostView::InkDropHostView()
     : ink_drop_event_handler_delegate_(this),
-      ink_drop_event_handler_(this, &ink_drop_event_handler_delegate_),
-      ink_drop_view_observer_(std::make_unique<InkDropViewObserver>(this)) {}
+      ink_drop_event_handler_(this, &ink_drop_event_handler_delegate_) {}
 
 InkDropHostView::~InkDropHostView() {
   // TODO(bruthig): Improve InkDropImpl to be safer about calling back to
diff --git a/ui/views/animation/ink_drop_host_view.h b/ui/views/animation/ink_drop_host_view.h
index 6473e37..9bb24ba 100644
--- a/ui/views/animation/ink_drop_host_view.h
+++ b/ui/views/animation/ink_drop_host_view.h
@@ -171,7 +171,11 @@
   // Provides access to |ink_drop_|. Implements lazy initialization of
   // |ink_drop_| so as to avoid virtual method calls during construction since
   // subclasses should be able to call SetInkDropMode() during construction.
-  InkDrop* GetInkDrop();
+  //
+  // WARNING: please don't override this; this is only virtual for the
+  // InstallableInkDrop refactor. TODO(crbug.com/931964): make non-virtual when
+  // this isn't necessary anymore.
+  virtual InkDrop* GetInkDrop();
 
   // Returns the point of the |last_ripple_triggering_event_| if it was a
   // LocatedEvent, otherwise the center point of the local bounds is returned.
@@ -188,7 +192,6 @@
   static gfx::Size CalculateLargeInkDropSize(const gfx::Size& small_size);
 
  private:
-  class InkDropViewObserver;
   friend class test::InkDropHostViewTestApi;
 
   class InkDropHostViewEventHandlerDelegate
@@ -222,9 +225,6 @@
   InkDropHostViewEventHandlerDelegate ink_drop_event_handler_delegate_;
   InkDropEventHandler ink_drop_event_handler_;
 
-  // Used to observe changes to the host through the ViewObserver API.
-  const std::unique_ptr<InkDropViewObserver> ink_drop_view_observer_;
-
   float ink_drop_visible_opacity_ = 0.175f;
 
   // TODO(pbos): Audit call sites to make sure highlight opacity is either
diff --git a/ui/views/animation/installable_ink_drop.cc b/ui/views/animation/installable_ink_drop.cc
new file mode 100644
index 0000000..8e826ee4
--- /dev/null
+++ b/ui/views/animation/installable_ink_drop.cc
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/installable_ink_drop.h"
+
+#include "base/logging.h"
+
+namespace views {
+
+const base::Feature kInstallableInkDropFeature{
+    "InstallableInkDrop", base::FEATURE_DISABLED_BY_DEFAULT};
+
+InstallableInkDrop::InstallableInkDrop() = default;
+
+InstallableInkDrop::~InstallableInkDrop() = default;
+
+void InstallableInkDrop::HostSizeChanged(const gfx::Size& new_size) {}
+
+InkDropState InstallableInkDrop::GetTargetInkDropState() const {
+  return current_state_;
+}
+
+void InstallableInkDrop::AnimateToState(InkDropState ink_drop_state) {
+  current_state_ = ink_drop_state;
+}
+
+void InstallableInkDrop::SetHoverHighlightFadeDurationMs(int duration_ms) {
+  NOTREACHED();
+}
+
+void InstallableInkDrop::UseDefaultHoverHighlightFadeDuration() {
+  NOTREACHED();
+}
+
+void InstallableInkDrop::SnapToActivated() {
+  NOTREACHED();
+}
+
+void InstallableInkDrop::SnapToHidden() {
+  NOTREACHED();
+}
+
+void InstallableInkDrop::SetHovered(bool is_hovered) {}
+
+void InstallableInkDrop::SetFocused(bool is_focused) {}
+
+bool InstallableInkDrop::IsHighlightFadingInOrVisible() const {
+  return false;
+}
+
+void InstallableInkDrop::SetShowHighlightOnHover(bool show_highlight_on_hover) {
+  NOTREACHED();
+}
+
+void InstallableInkDrop::SetShowHighlightOnFocus(bool show_highlight_on_focus) {
+  NOTREACHED();
+}
+
+}  // namespace views
diff --git a/ui/views/animation/installable_ink_drop.h b/ui/views/animation/installable_ink_drop.h
new file mode 100644
index 0000000..0670195
--- /dev/null
+++ b/ui/views/animation/installable_ink_drop.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_H_
+#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_H_
+
+#include "base/feature_list.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/animation/ink_drop.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+extern const VIEWS_EXPORT base::Feature kInstallableInkDropFeature;
+
+// Stub for future InkDrop implementation that will be installable on any View
+// without needing InkDropHostView. This is currently non-functional and fails
+// on some method calls. TODO(crbug.com/931964): implement the necessary parts
+// of the API and remove the rest from the InkDrop interface.
+class VIEWS_EXPORT InstallableInkDrop : public InkDrop {
+ public:
+  InstallableInkDrop();
+  ~InstallableInkDrop() override;
+
+  // InkDrop:
+  void HostSizeChanged(const gfx::Size& new_size) override;
+  InkDropState GetTargetInkDropState() const override;
+  void AnimateToState(InkDropState ink_drop_state) override;
+  void SetHoverHighlightFadeDurationMs(int duration_ms) override;
+  void UseDefaultHoverHighlightFadeDuration() override;
+  void SnapToActivated() override;
+  void SnapToHidden() override;
+  void SetHovered(bool is_hovered) override;
+  void SetFocused(bool is_focused) override;
+  bool IsHighlightFadingInOrVisible() const override;
+  void SetShowHighlightOnHover(bool show_highlight_on_hover) override;
+  void SetShowHighlightOnFocus(bool show_highlight_on_focus) override;
+
+ private:
+  InkDropState current_state_ = InkDropState::HIDDEN;
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_H_
diff --git a/ui/views/animation/installable_ink_drop_unittest.cc b/ui/views/animation/installable_ink_drop_unittest.cc
new file mode 100644
index 0000000..d75acae
--- /dev/null
+++ b/ui/views/animation/installable_ink_drop_unittest.cc
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/installable_ink_drop.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/animation/ink_drop_state.h"
+
+namespace views {
+
+TEST(InstallableInkDropTest, UpdatesState) {
+  InstallableInkDrop installable_ink_drop;
+
+  // Initial state should be HIDDEN.
+  EXPECT_EQ(installable_ink_drop.GetTargetInkDropState(), InkDropState::HIDDEN);
+
+  installable_ink_drop.AnimateToState(InkDropState::ACTIVATED);
+  EXPECT_EQ(installable_ink_drop.GetTargetInkDropState(),
+            InkDropState::ACTIVATED);
+}
+
+}  // namespace views
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
index 86c7b558..f8c2e3e 100644
--- a/ui/views/controls/native/native_view_host.cc
+++ b/ui/views/controls/native/native_view_host.cc
@@ -68,6 +68,10 @@
   native_wrapper_->SetHitTestTopInset(top_inset);
 }
 
+int NativeViewHost::GetHitTestTopInset() const {
+  return native_wrapper_->GetHitTestTopInset();
+}
+
 void NativeViewHost::SetNativeViewSize(const gfx::Size& size) {
   if (native_view_size_ == size)
     return;
diff --git a/ui/views/controls/native/native_view_host.h b/ui/views/controls/native/native_view_host.h
index 5923cc46..a370cee 100644
--- a/ui/views/controls/native/native_view_host.h
+++ b/ui/views/controls/native/native_view_host.h
@@ -61,6 +61,7 @@
   // targeted. This will be used when another view is covering there
   // temporarily, like the immersive fullscreen mode of ChromeOS.
   void SetHitTestTopInset(int top_inset);
+  int GetHitTestTopInset() const;
 
   // Sets the size for the NativeView that may or may not match the size of this
   // View when it is being captured. If the size does not match, scaling will
diff --git a/ui/views/controls/native/native_view_host_aura.cc b/ui/views/controls/native/native_view_host_aura.cc
index e603d41..293814b0 100644
--- a/ui/views/controls/native/native_view_host_aura.cc
+++ b/ui/views/controls/native/native_view_host_aura.cc
@@ -186,6 +186,10 @@
       new gfx::Rect(host_->ConvertRectToWidget(gfx::Rect(x, y, w, h))));
 }
 
+int NativeViewHostAura::GetHitTestTopInset() const {
+  return top_inset_;
+}
+
 bool NativeViewHostAura::HasInstalledClip() {
   return !!clip_rect_;
 }
diff --git a/ui/views/controls/native/native_view_host_aura.h b/ui/views/controls/native/native_view_host_aura.h
index ea29802..26381af 100644
--- a/ui/views/controls/native/native_view_host_aura.h
+++ b/ui/views/controls/native/native_view_host_aura.h
@@ -35,6 +35,7 @@
   void RemovedFromWidget() override;
   bool SetCustomMask(std::unique_ptr<ui::LayerOwner> mask) override;
   void SetHitTestTopInset(int top_inset) override;
+  int GetHitTestTopInset() const override;
   void InstallClip(int x, int y, int w, int h) override;
   bool HasInstalledClip() override;
   void UninstallClip() override;
diff --git a/ui/views/controls/native/native_view_host_mac.h b/ui/views/controls/native/native_view_host_mac.h
index cfcd98f..c9945f76 100644
--- a/ui/views/controls/native/native_view_host_mac.h
+++ b/ui/views/controls/native/native_view_host_mac.h
@@ -42,6 +42,7 @@
   void RemovedFromWidget() override;
   bool SetCustomMask(std::unique_ptr<ui::LayerOwner> mask) override;
   void SetHitTestTopInset(int top_inset) override;
+  int GetHitTestTopInset() const override;
   void InstallClip(int x, int y, int w, int h) override;
   bool HasInstalledClip() override;
   void UninstallClip() override;
diff --git a/ui/views/controls/native/native_view_host_mac.mm b/ui/views/controls/native/native_view_host_mac.mm
index 6fda67ff..b4c366f 100644
--- a/ui/views/controls/native/native_view_host_mac.mm
+++ b/ui/views/controls/native/native_view_host_mac.mm
@@ -191,6 +191,11 @@
   NOTIMPLEMENTED();
 }
 
+int NativeViewHostMac::GetHitTestTopInset() const {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
 void NativeViewHostMac::InstallClip(int x, int y, int w, int h) {
   NOTIMPLEMENTED();
 }
diff --git a/ui/views/controls/native/native_view_host_wrapper.h b/ui/views/controls/native/native_view_host_wrapper.h
index d43cc71..f4208674 100644
--- a/ui/views/controls/native/native_view_host_wrapper.h
+++ b/ui/views/controls/native/native_view_host_wrapper.h
@@ -49,6 +49,7 @@
   // Sets the height of the top region where gfx::NativeView shouldn't be
   // targeted.
   virtual void SetHitTestTopInset(int top_inset) = 0;
+  virtual int GetHitTestTopInset() const = 0;
 
   // Installs a clip on the gfx::NativeView. These values are in the coordinate
   // space of the Widget, so if this method is called from ShowWidget
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc
index ad63c545..0529adb8267 100644
--- a/ui/views/mus/mus_client.cc
+++ b/ui/views/mus/mus_client.cc
@@ -116,10 +116,11 @@
     }
   }
 
-  ViewsDelegate::GetInstance()->set_native_widget_factory(
-      base::Bind(&MusClient::CreateNativeWidget, base::Unretained(this)));
-  ViewsDelegate::GetInstance()->set_desktop_window_tree_host_factory(base::Bind(
-      &MusClient::CreateDesktopWindowTreeHost, base::Unretained(this)));
+  ViewsDelegate::GetInstance()->set_native_widget_factory(base::BindRepeating(
+      &MusClient::CreateNativeWidget, base::Unretained(this)));
+  ViewsDelegate::GetInstance()->set_desktop_window_tree_host_factory(
+      base::BindRepeating(&MusClient::CreateDesktopWindowTreeHost,
+                          base::Unretained(this)));
 }
 
 MusClient::~MusClient() {
diff --git a/ui/views/views_delegate.h b/ui/views/views_delegate.h
index 1a66e7d..41728e3 100644
--- a/ui/views/views_delegate.h
+++ b/ui/views/views_delegate.h
@@ -57,11 +57,11 @@
 class VIEWS_EXPORT ViewsDelegate {
  public:
   using NativeWidgetFactory =
-      base::Callback<NativeWidget*(const Widget::InitParams&,
-                                   internal::NativeWidgetDelegate*)>;
+      base::RepeatingCallback<NativeWidget*(const Widget::InitParams&,
+                                            internal::NativeWidgetDelegate*)>;
 #if defined(USE_AURA)
   using DesktopWindowTreeHostFactory =
-      base::Callback<std::unique_ptr<DesktopWindowTreeHost>(
+      base::RepeatingCallback<std::unique_ptr<DesktopWindowTreeHost>(
           const Widget::InitParams&,
           internal::NativeWidgetDelegate*,
           DesktopNativeWidgetAura*)>;
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js b/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
index bddc345..d050d08 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
@@ -18,7 +18,8 @@
  *   controlledSettingRecommendedMatches: string,
  *   controlledSettingRecommendedDiffers: string,
  *   controlledSettingShared: (string|undefined),
- *   controlledSettingOwner: (string|undefined),
+ *   controlledSettingWithOwner: string,
+ *   controlledSettingNoOwner: string,
  * }}
  */
 // eslint-disable-next-line no-var
@@ -124,7 +125,9 @@
       case CrPolicyIndicatorType.PRIMARY_USER:
         return CrPolicyStrings.controlledSettingShared.replace('$1', name);
       case CrPolicyIndicatorType.OWNER:
-        return CrPolicyStrings.controlledSettingOwner.replace('$1', name);
+        return name.length > 0 ?
+            CrPolicyStrings.controlledSettingWithOwner.replace('$1', name) :
+            CrPolicyStrings.controlledSettingNoOwner;
       case CrPolicyIndicatorType.USER_POLICY:
       case CrPolicyIndicatorType.DEVICE_POLICY:
         return CrPolicyStrings.controlledSettingPolicy;